@hero-design/rn 8.134.0 → 8.135.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/es/index.js +235 -78
- package/lib/index.js +232 -74
- package/package.json +1 -1
- package/src/components/List/BasicListItem.tsx +2 -2
- package/src/components/List/index.tsx +3 -0
- package/src/components/SectionList/SectionList.tsx +181 -0
- package/src/components/SectionList/StyledSectionList.tsx +65 -0
- package/src/components/SectionList/index.tsx +4 -0
- package/src/index.ts +2 -0
- package/src/theme/components/sectionList.ts +31 -0
- package/src/theme/getTheme.ts +3 -0
- package/src/types.ts +1 -0
- package/types/components/List/BasicListItem.d.ts +2 -2
- package/types/components/List/index.d.ts +2 -0
- package/types/components/Radio/StyledRadio.d.ts +1 -1
- package/types/components/SectionList/SectionList.d.ts +66 -0
- package/types/components/SectionList/StyledSectionList.d.ts +33 -0
- package/types/components/SectionList/index.d.ts +3 -0
- package/types/index.d.ts +2 -1
- package/types/theme/components/sectionList.d.ts +23 -0
- package/types/theme/getTheme.d.ts +2 -0
- package/types/types.d.ts +1 -0
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
import type { IconName } from '../Icon';
|
|
13
13
|
import { useTheme } from '../../theme';
|
|
14
14
|
|
|
15
|
-
interface
|
|
15
|
+
export interface BasicListItemProps {
|
|
16
16
|
/**
|
|
17
17
|
* Name of Icon or component to render on the left side of title.
|
|
18
18
|
*/
|
|
@@ -61,7 +61,7 @@ const BasicListItem = ({
|
|
|
61
61
|
selected = false,
|
|
62
62
|
disabled = false,
|
|
63
63
|
onPress,
|
|
64
|
-
}:
|
|
64
|
+
}: BasicListItemProps): ReactElement => {
|
|
65
65
|
const theme = useTheme();
|
|
66
66
|
|
|
67
67
|
return (
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import ListItem from './ListItem';
|
|
2
2
|
import BasicListItem from './BasicListItem';
|
|
3
3
|
|
|
4
|
+
export type { ListItemProps } from './ListItem';
|
|
5
|
+
export type { BasicListItemProps } from './BasicListItem';
|
|
6
|
+
|
|
4
7
|
interface ListType {
|
|
5
8
|
Item: typeof ListItem;
|
|
6
9
|
BasicItem: typeof BasicListItem;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
|
|
3
|
+
import type { ReactElement } from 'react';
|
|
4
|
+
import type {
|
|
5
|
+
SectionListProps as RNSectionListPropsType,
|
|
6
|
+
StyleProp,
|
|
7
|
+
ViewStyle,
|
|
8
|
+
} from 'react-native';
|
|
9
|
+
import { SectionList as RNSectionList } from 'react-native';
|
|
10
|
+
import Divider from '../Divider';
|
|
11
|
+
import List from '../List';
|
|
12
|
+
import type { BasicListItemProps } from '../List/BasicListItem';
|
|
13
|
+
import type { ListItemProps } from '../List/ListItem';
|
|
14
|
+
import type { SectionHeadingProps } from '../SectionHeading';
|
|
15
|
+
import type { MarginHorizontal, RowPosition } from './StyledSectionList';
|
|
16
|
+
import {
|
|
17
|
+
StyledDividerWrapper,
|
|
18
|
+
StyledRow,
|
|
19
|
+
StyledSectionHeading,
|
|
20
|
+
StyledSectionSpacer,
|
|
21
|
+
} from './StyledSectionList';
|
|
22
|
+
|
|
23
|
+
type SectionHeadingConfig = Pick<
|
|
24
|
+
SectionHeadingProps,
|
|
25
|
+
'text' | 'icon' | 'rightChildren' | 'intent' | 'size'
|
|
26
|
+
>;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* A single row inside a section. `type` is a discriminant that selects the row component:
|
|
30
|
+
* - `'basic-item'` renders `List.BasicItem` (icon/text, no children)
|
|
31
|
+
* - `'list-item'` renders `List.Item` (supports subtitle, children, leading status)
|
|
32
|
+
*
|
|
33
|
+
* `variant` is omitted from `list-item` — rows always render full-width inside a section group.
|
|
34
|
+
* `key` is an optional stable identifier for use with a custom `keyExtractor`.
|
|
35
|
+
* Mix both types freely within the same `data` array.
|
|
36
|
+
*/
|
|
37
|
+
export type SectionListRow =
|
|
38
|
+
| ({ type: 'basic-item'; key?: string } & BasicListItemProps)
|
|
39
|
+
| ({ type: 'list-item'; key?: string } & Omit<ListItemProps, 'variant'>);
|
|
40
|
+
|
|
41
|
+
export interface SectionData extends Omit<SectionHeadingConfig, 'text'> {
|
|
42
|
+
/**
|
|
43
|
+
* Unique key for this section.
|
|
44
|
+
*/
|
|
45
|
+
key: string;
|
|
46
|
+
/**
|
|
47
|
+
* Rows to render. Each row is a `basic-item` or `list-item` variant; mix freely, in any order.
|
|
48
|
+
*/
|
|
49
|
+
data: SectionListRow[];
|
|
50
|
+
/**
|
|
51
|
+
* Heading text. Required unless `hideHeading` is `true`.
|
|
52
|
+
*/
|
|
53
|
+
text?: SectionHeadingConfig['text'];
|
|
54
|
+
/**
|
|
55
|
+
* When true, the section heading is not rendered. Rows are still shown. Defaults to false.
|
|
56
|
+
*/
|
|
57
|
+
hideHeading?: boolean;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
type RNSectionListProps = RNSectionListPropsType<SectionListRow, SectionData>;
|
|
61
|
+
|
|
62
|
+
// Layout (dividers, headers, corner rounding, spacing) is owned by this component, so these
|
|
63
|
+
// RN props are not user-configurable — everything else on RN's SectionList passes through.
|
|
64
|
+
type OmittedRNSectionListProps =
|
|
65
|
+
| 'sections'
|
|
66
|
+
| 'renderSectionHeader'
|
|
67
|
+
| 'renderItem'
|
|
68
|
+
| 'ItemSeparatorComponent'
|
|
69
|
+
| 'SectionSeparatorComponent'
|
|
70
|
+
| 'stickySectionHeadersEnabled';
|
|
71
|
+
|
|
72
|
+
export interface SectionListProps
|
|
73
|
+
extends Omit<RNSectionListProps, OmittedRNSectionListProps> {
|
|
74
|
+
/**
|
|
75
|
+
* Sections to render. Each section carries SectionHeading props plus a `data` array,
|
|
76
|
+
* mirroring React Native's SectionList section shape.
|
|
77
|
+
*/
|
|
78
|
+
sections: SectionData[];
|
|
79
|
+
/**
|
|
80
|
+
* Horizontal margin applied to each row group and its dividers, preventing content from
|
|
81
|
+
* rendering flush against the screen edge. Defaults to `'medium'` (16 px).
|
|
82
|
+
* Pass `'none'` when the parent screen already applies its own side gutter.
|
|
83
|
+
*/
|
|
84
|
+
marginHorizontal?: MarginHorizontal;
|
|
85
|
+
/**
|
|
86
|
+
* Additional style on the underlying RN SectionList.
|
|
87
|
+
*/
|
|
88
|
+
style?: StyleProp<ViewStyle>;
|
|
89
|
+
/**
|
|
90
|
+
* Testing id of the component.
|
|
91
|
+
*/
|
|
92
|
+
testID?: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const positionOf = (index: number, count: number): RowPosition => {
|
|
96
|
+
if (count === 1) return 'single';
|
|
97
|
+
if (index === 0) return 'top';
|
|
98
|
+
if (index === count - 1) return 'bottom';
|
|
99
|
+
return 'middle';
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// StyledRow already clips corners via overflow:hidden + its own borderRadius, so the
|
|
103
|
+
// inner list items must not add their own rounding on top of it.
|
|
104
|
+
const NO_RADIUS = { borderRadius: 0 } as const;
|
|
105
|
+
|
|
106
|
+
const renderRow = (row: SectionListRow): ReactElement =>
|
|
107
|
+
row.type === 'basic-item' ? (
|
|
108
|
+
<List.BasicItem {...row} style={[NO_RADIUS, row.style]} />
|
|
109
|
+
) : (
|
|
110
|
+
<List.Item {...row} style={[NO_RADIUS, row.style]} />
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
// Factory lives at module scope — satisfies react/no-unstable-nested-components.
|
|
114
|
+
// RN only renders ItemSeparatorComponent between adjacent items (never after the
|
|
115
|
+
// last), which is exactly the desired divider placement for a bounded group.
|
|
116
|
+
const createRowDivider = (margin: MarginHorizontal | undefined) => () =>
|
|
117
|
+
(
|
|
118
|
+
<StyledDividerWrapper
|
|
119
|
+
testID="section-list-divider-wrapper"
|
|
120
|
+
themeMarginHorizontal={margin}
|
|
121
|
+
>
|
|
122
|
+
<Divider testID="section-list-divider" />
|
|
123
|
+
</StyledDividerWrapper>
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
const SectionSpacer: NonNullable<
|
|
127
|
+
RNSectionListProps['SectionSeparatorComponent']
|
|
128
|
+
> = ({ leadingItem, trailingSection }) =>
|
|
129
|
+
leadingItem && trailingSection ? (
|
|
130
|
+
<StyledSectionSpacer
|
|
131
|
+
themeCompact={!!trailingSection.hideHeading}
|
|
132
|
+
testID="section-list-spacer"
|
|
133
|
+
/>
|
|
134
|
+
) : null;
|
|
135
|
+
|
|
136
|
+
function SectionList({
|
|
137
|
+
sections,
|
|
138
|
+
marginHorizontal = 'medium',
|
|
139
|
+
style,
|
|
140
|
+
testID,
|
|
141
|
+
...rest
|
|
142
|
+
}: SectionListProps): ReactElement {
|
|
143
|
+
const RowDivider = useMemo(
|
|
144
|
+
() => createRowDivider(marginHorizontal),
|
|
145
|
+
[marginHorizontal]
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
return (
|
|
149
|
+
<RNSectionList<SectionListRow, SectionData>
|
|
150
|
+
{...rest}
|
|
151
|
+
style={style}
|
|
152
|
+
testID={testID}
|
|
153
|
+
sections={sections}
|
|
154
|
+
stickySectionHeadersEnabled={false}
|
|
155
|
+
ItemSeparatorComponent={RowDivider}
|
|
156
|
+
renderSectionHeader={({ section }) =>
|
|
157
|
+
section.hideHeading ? null : (
|
|
158
|
+
<StyledSectionHeading
|
|
159
|
+
text={section.text ?? ''}
|
|
160
|
+
icon={section.icon}
|
|
161
|
+
rightChildren={section.rightChildren}
|
|
162
|
+
intent={section.intent}
|
|
163
|
+
size={section.size}
|
|
164
|
+
/>
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
renderItem={({ item, index, section }) => (
|
|
168
|
+
<StyledRow
|
|
169
|
+
testID="section-list-row"
|
|
170
|
+
themePosition={positionOf(index, section.data.length)}
|
|
171
|
+
themeMarginHorizontal={marginHorizontal}
|
|
172
|
+
>
|
|
173
|
+
{renderRow(item)}
|
|
174
|
+
</StyledRow>
|
|
175
|
+
)}
|
|
176
|
+
SectionSeparatorComponent={SectionSpacer}
|
|
177
|
+
/>
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export default SectionList;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { View } from 'react-native';
|
|
2
|
+
import styled from '@emotion/native';
|
|
3
|
+
import SectionHeading from '../SectionHeading';
|
|
4
|
+
|
|
5
|
+
export type RowPosition = 'top' | 'bottom' | 'middle' | 'single';
|
|
6
|
+
|
|
7
|
+
export type MarginHorizontal =
|
|
8
|
+
| 'xsmall'
|
|
9
|
+
| 'small'
|
|
10
|
+
| 'medium'
|
|
11
|
+
| 'large'
|
|
12
|
+
| 'xlarge'
|
|
13
|
+
| 'none';
|
|
14
|
+
|
|
15
|
+
const isTop = (position: RowPosition) =>
|
|
16
|
+
position === 'top' || position === 'single';
|
|
17
|
+
const isBottom = (position: RowPosition) =>
|
|
18
|
+
position === 'bottom' || position === 'single';
|
|
19
|
+
|
|
20
|
+
const StyledRow = styled(View)<{
|
|
21
|
+
themePosition: RowPosition;
|
|
22
|
+
themeMarginHorizontal?: MarginHorizontal;
|
|
23
|
+
}>(({ theme, themePosition, themeMarginHorizontal = 'medium' }) => {
|
|
24
|
+
const radius = theme.__hd__.sectionList.radii.group;
|
|
25
|
+
const marginHorizontal =
|
|
26
|
+
theme.__hd__.sectionList.space.marginHorizontal[themeMarginHorizontal];
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
marginHorizontal,
|
|
30
|
+
backgroundColor: theme.__hd__.sectionList.colors.groupBackground,
|
|
31
|
+
borderTopLeftRadius: isTop(themePosition) ? radius : 0,
|
|
32
|
+
borderTopRightRadius: isTop(themePosition) ? radius : 0,
|
|
33
|
+
borderBottomLeftRadius: isBottom(themePosition) ? radius : 0,
|
|
34
|
+
borderBottomRightRadius: isBottom(themePosition) ? radius : 0,
|
|
35
|
+
overflow: 'hidden',
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const StyledDividerWrapper = styled(View)<{
|
|
40
|
+
themeMarginHorizontal?: MarginHorizontal;
|
|
41
|
+
}>(({ theme, themeMarginHorizontal = 'medium' }) => ({
|
|
42
|
+
marginHorizontal:
|
|
43
|
+
theme.__hd__.sectionList.space.marginHorizontal[themeMarginHorizontal],
|
|
44
|
+
backgroundColor: theme.__hd__.sectionList.colors.groupBackground,
|
|
45
|
+
}));
|
|
46
|
+
|
|
47
|
+
const StyledSectionSpacer = styled(View)<{ themeCompact: boolean }>(
|
|
48
|
+
({ theme, themeCompact }) => ({
|
|
49
|
+
height: themeCompact
|
|
50
|
+
? theme.__hd__.sectionList.space.sectionSpacingCompact
|
|
51
|
+
: theme.__hd__.sectionList.space.sectionSpacing,
|
|
52
|
+
})
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const StyledSectionHeading = styled(SectionHeading)(({ theme }) => ({
|
|
56
|
+
paddingLeft: theme.__hd__.sectionList.space.headingPaddingLeft,
|
|
57
|
+
marginBottom: 0,
|
|
58
|
+
}));
|
|
59
|
+
|
|
60
|
+
export {
|
|
61
|
+
StyledRow,
|
|
62
|
+
StyledDividerWrapper,
|
|
63
|
+
StyledSectionSpacer,
|
|
64
|
+
StyledSectionHeading,
|
|
65
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -63,6 +63,7 @@ import Spinner from './components/Spinner';
|
|
|
63
63
|
import Swipeable from './components/Swipeable';
|
|
64
64
|
import Radio from './components/Radio';
|
|
65
65
|
import SectionHeading from './components/SectionHeading';
|
|
66
|
+
import SectionList from './components/SectionList';
|
|
66
67
|
import Select from './components/Select';
|
|
67
68
|
import Skeleton from './components/Skeleton';
|
|
68
69
|
import Success from './components/StatusScreens/Success';
|
|
@@ -162,6 +163,7 @@ export {
|
|
|
162
163
|
SegmentedControl,
|
|
163
164
|
ScrollViewWithFAB,
|
|
164
165
|
SectionHeading,
|
|
166
|
+
SectionList,
|
|
165
167
|
SectionListWithFAB,
|
|
166
168
|
Select,
|
|
167
169
|
Success,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { GlobalTheme } from '../global';
|
|
2
|
+
|
|
3
|
+
const getSectionListTheme = (theme: GlobalTheme) => {
|
|
4
|
+
const colors = {
|
|
5
|
+
groupBackground: theme.colors.defaultGlobalSurface,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const radii = {
|
|
9
|
+
group: theme.radii.xlarge,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const marginHorizontalValues = {
|
|
13
|
+
none: 0,
|
|
14
|
+
xsmall: theme.space.xsmall,
|
|
15
|
+
small: theme.space.small,
|
|
16
|
+
medium: theme.space.medium,
|
|
17
|
+
large: theme.space.large,
|
|
18
|
+
xlarge: theme.space.xlarge,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const space = {
|
|
22
|
+
marginHorizontal: marginHorizontalValues,
|
|
23
|
+
sectionSpacing: theme.space.medium,
|
|
24
|
+
sectionSpacingCompact: theme.space.small,
|
|
25
|
+
headingPaddingLeft: theme.space.small,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
return { colors, radii, space };
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default getSectionListTheme;
|
package/src/theme/getTheme.ts
CHANGED
|
@@ -41,6 +41,7 @@ import getRateTheme from './components/rate';
|
|
|
41
41
|
import getRefreshControlTheme from './components/refreshControl';
|
|
42
42
|
import getRichTextEditorTheme from './components/richTextEditor';
|
|
43
43
|
import getSectionHeadingTheme from './components/sectionHeading';
|
|
44
|
+
import getSectionListTheme from './components/sectionList';
|
|
44
45
|
import getSelectTheme from './components/select';
|
|
45
46
|
import getSkeletonTheme from './components/skeleton';
|
|
46
47
|
import getSliderTheme from './components/slider';
|
|
@@ -115,6 +116,7 @@ type Theme = GlobalTheme & {
|
|
|
115
116
|
richTextEditor: ReturnType<typeof getRichTextEditorTheme>;
|
|
116
117
|
search: ReturnType<typeof getSearchTheme>;
|
|
117
118
|
sectionHeading: ReturnType<typeof getSectionHeadingTheme>;
|
|
119
|
+
sectionList: ReturnType<typeof getSectionListTheme>;
|
|
118
120
|
select: ReturnType<typeof getSelectTheme>;
|
|
119
121
|
skeleton: ReturnType<typeof getSkeletonTheme>;
|
|
120
122
|
slider: ReturnType<typeof getSliderTheme>;
|
|
@@ -183,6 +185,7 @@ const getTheme = (
|
|
|
183
185
|
richTextEditor: getRichTextEditorTheme(globalTheme),
|
|
184
186
|
search: getSearchTheme(globalTheme),
|
|
185
187
|
sectionHeading: getSectionHeadingTheme(globalTheme),
|
|
188
|
+
sectionList: getSectionListTheme(globalTheme),
|
|
186
189
|
select: getSelectTheme(globalTheme),
|
|
187
190
|
skeleton: getSkeletonTheme(globalTheme),
|
|
188
191
|
slider: getSliderTheme(globalTheme),
|
package/src/types.ts
CHANGED
|
@@ -117,3 +117,4 @@ export type { SkeletonProps } from './components/Skeleton';
|
|
|
117
117
|
export type { SpinnerProps } from './components/Spinner';
|
|
118
118
|
export type { SwitchProps } from './components/Switch';
|
|
119
119
|
export type { TagProps } from './components/Tag';
|
|
120
|
+
export type { SectionListProps } from './components/SectionList';
|
|
@@ -2,7 +2,7 @@ import type { ReactElement } from 'react';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import type { StyleProp, ViewStyle } from 'react-native';
|
|
4
4
|
import type { IconName } from '../Icon';
|
|
5
|
-
interface
|
|
5
|
+
export interface BasicListItemProps {
|
|
6
6
|
/**
|
|
7
7
|
* Name of Icon or component to render on the left side of title.
|
|
8
8
|
*/
|
|
@@ -40,5 +40,5 @@ interface ListItemProps {
|
|
|
40
40
|
*/
|
|
41
41
|
onPress?: () => void;
|
|
42
42
|
}
|
|
43
|
-
declare const BasicListItem: ({ prefix, suffix, title, subtitle, style, testID, selected, disabled, onPress, }:
|
|
43
|
+
declare const BasicListItem: ({ prefix, suffix, title, subtitle, style, testID, selected, disabled, onPress, }: BasicListItemProps) => ReactElement;
|
|
44
44
|
export default BasicListItem;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import ListItem from './ListItem';
|
|
2
2
|
import BasicListItem from './BasicListItem';
|
|
3
|
+
export type { ListItemProps } from './ListItem';
|
|
4
|
+
export type { BasicListItemProps } from './BasicListItem';
|
|
3
5
|
interface ListType {
|
|
4
6
|
Item: typeof ListItem;
|
|
5
7
|
BasicItem: typeof BasicListItem;
|
|
@@ -20,7 +20,7 @@ declare const Spacer: import("@emotion/native").StyledComponent<import("react-na
|
|
|
20
20
|
}, {}, {
|
|
21
21
|
ref?: import("react").Ref<View> | undefined;
|
|
22
22
|
}>;
|
|
23
|
-
declare const StyledRadio: import("@emotion/native").StyledComponent<import("
|
|
23
|
+
declare const StyledRadio: import("@emotion/native").StyledComponent<import("../List").ListItemProps & {
|
|
24
24
|
theme?: import("@emotion/react").Theme;
|
|
25
25
|
as?: React.ElementType;
|
|
26
26
|
} & {
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import type { SectionListProps as RNSectionListPropsType, StyleProp, ViewStyle } from 'react-native';
|
|
3
|
+
import type { BasicListItemProps } from '../List/BasicListItem';
|
|
4
|
+
import type { ListItemProps } from '../List/ListItem';
|
|
5
|
+
import type { SectionHeadingProps } from '../SectionHeading';
|
|
6
|
+
import type { MarginHorizontal } from './StyledSectionList';
|
|
7
|
+
type SectionHeadingConfig = Pick<SectionHeadingProps, 'text' | 'icon' | 'rightChildren' | 'intent' | 'size'>;
|
|
8
|
+
/**
|
|
9
|
+
* A single row inside a section. `type` is a discriminant that selects the row component:
|
|
10
|
+
* - `'basic-item'` renders `List.BasicItem` (icon/text, no children)
|
|
11
|
+
* - `'list-item'` renders `List.Item` (supports subtitle, children, leading status)
|
|
12
|
+
*
|
|
13
|
+
* `variant` is omitted from `list-item` — rows always render full-width inside a section group.
|
|
14
|
+
* `key` is an optional stable identifier for use with a custom `keyExtractor`.
|
|
15
|
+
* Mix both types freely within the same `data` array.
|
|
16
|
+
*/
|
|
17
|
+
export type SectionListRow = ({
|
|
18
|
+
type: 'basic-item';
|
|
19
|
+
key?: string;
|
|
20
|
+
} & BasicListItemProps) | ({
|
|
21
|
+
type: 'list-item';
|
|
22
|
+
key?: string;
|
|
23
|
+
} & Omit<ListItemProps, 'variant'>);
|
|
24
|
+
export interface SectionData extends Omit<SectionHeadingConfig, 'text'> {
|
|
25
|
+
/**
|
|
26
|
+
* Unique key for this section.
|
|
27
|
+
*/
|
|
28
|
+
key: string;
|
|
29
|
+
/**
|
|
30
|
+
* Rows to render. Each row is a `basic-item` or `list-item` variant; mix freely, in any order.
|
|
31
|
+
*/
|
|
32
|
+
data: SectionListRow[];
|
|
33
|
+
/**
|
|
34
|
+
* Heading text. Required unless `hideHeading` is `true`.
|
|
35
|
+
*/
|
|
36
|
+
text?: SectionHeadingConfig['text'];
|
|
37
|
+
/**
|
|
38
|
+
* When true, the section heading is not rendered. Rows are still shown. Defaults to false.
|
|
39
|
+
*/
|
|
40
|
+
hideHeading?: boolean;
|
|
41
|
+
}
|
|
42
|
+
type RNSectionListProps = RNSectionListPropsType<SectionListRow, SectionData>;
|
|
43
|
+
type OmittedRNSectionListProps = 'sections' | 'renderSectionHeader' | 'renderItem' | 'ItemSeparatorComponent' | 'SectionSeparatorComponent' | 'stickySectionHeadersEnabled';
|
|
44
|
+
export interface SectionListProps extends Omit<RNSectionListProps, OmittedRNSectionListProps> {
|
|
45
|
+
/**
|
|
46
|
+
* Sections to render. Each section carries SectionHeading props plus a `data` array,
|
|
47
|
+
* mirroring React Native's SectionList section shape.
|
|
48
|
+
*/
|
|
49
|
+
sections: SectionData[];
|
|
50
|
+
/**
|
|
51
|
+
* Horizontal margin applied to each row group and its dividers, preventing content from
|
|
52
|
+
* rendering flush against the screen edge. Defaults to `'medium'` (16 px).
|
|
53
|
+
* Pass `'none'` when the parent screen already applies its own side gutter.
|
|
54
|
+
*/
|
|
55
|
+
marginHorizontal?: MarginHorizontal;
|
|
56
|
+
/**
|
|
57
|
+
* Additional style on the underlying RN SectionList.
|
|
58
|
+
*/
|
|
59
|
+
style?: StyleProp<ViewStyle>;
|
|
60
|
+
/**
|
|
61
|
+
* Testing id of the component.
|
|
62
|
+
*/
|
|
63
|
+
testID?: string;
|
|
64
|
+
}
|
|
65
|
+
declare function SectionList({ sections, marginHorizontal, style, testID, ...rest }: SectionListProps): ReactElement;
|
|
66
|
+
export default SectionList;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { View } from 'react-native';
|
|
2
|
+
export type RowPosition = 'top' | 'bottom' | 'middle' | 'single';
|
|
3
|
+
export type MarginHorizontal = 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'none';
|
|
4
|
+
declare const StyledRow: import("@emotion/native").StyledComponent<import("react-native").ViewProps & {
|
|
5
|
+
theme?: import("@emotion/react").Theme;
|
|
6
|
+
as?: React.ElementType;
|
|
7
|
+
} & {
|
|
8
|
+
themePosition: RowPosition;
|
|
9
|
+
themeMarginHorizontal?: MarginHorizontal;
|
|
10
|
+
}, {}, {
|
|
11
|
+
ref?: import("react").Ref<View> | undefined;
|
|
12
|
+
}>;
|
|
13
|
+
declare const StyledDividerWrapper: import("@emotion/native").StyledComponent<import("react-native").ViewProps & {
|
|
14
|
+
theme?: import("@emotion/react").Theme;
|
|
15
|
+
as?: React.ElementType;
|
|
16
|
+
} & {
|
|
17
|
+
themeMarginHorizontal?: MarginHorizontal;
|
|
18
|
+
}, {}, {
|
|
19
|
+
ref?: import("react").Ref<View> | undefined;
|
|
20
|
+
}>;
|
|
21
|
+
declare const StyledSectionSpacer: import("@emotion/native").StyledComponent<import("react-native").ViewProps & {
|
|
22
|
+
theme?: import("@emotion/react").Theme;
|
|
23
|
+
as?: React.ElementType;
|
|
24
|
+
} & {
|
|
25
|
+
themeCompact: boolean;
|
|
26
|
+
}, {}, {
|
|
27
|
+
ref?: import("react").Ref<View> | undefined;
|
|
28
|
+
}>;
|
|
29
|
+
declare const StyledSectionHeading: import("@emotion/native").StyledComponent<import("../SectionHeading").SectionHeadingProps & {
|
|
30
|
+
theme?: import("@emotion/react").Theme;
|
|
31
|
+
as?: React.ElementType;
|
|
32
|
+
}, {}, {}>;
|
|
33
|
+
export { StyledRow, StyledDividerWrapper, StyledSectionSpacer, StyledSectionHeading, };
|
package/types/index.d.ts
CHANGED
|
@@ -39,6 +39,7 @@ import Spinner from './components/Spinner';
|
|
|
39
39
|
import Swipeable from './components/Swipeable';
|
|
40
40
|
import Radio from './components/Radio';
|
|
41
41
|
import SectionHeading from './components/SectionHeading';
|
|
42
|
+
import SectionList from './components/SectionList';
|
|
42
43
|
import Select from './components/Select';
|
|
43
44
|
import Skeleton from './components/Skeleton';
|
|
44
45
|
import Success from './components/StatusScreens/Success';
|
|
@@ -62,6 +63,6 @@ import FloatingIsland from './components/FloatingIsland';
|
|
|
62
63
|
import LocaleProvider from './components/LocaleProvider';
|
|
63
64
|
import FilterTrigger from './components/FilterTrigger';
|
|
64
65
|
import InlineLoader, { type InlineLoaderProps } from './components/InlineLoader';
|
|
65
|
-
export { theme, getTheme, useTheme, scale, ThemeProvider, ThemeSwitcher, withTheme, swagSystemPalette, swagLightSystemPalette, swagLightJobsSystemPalette, swagDarkSystemPalette, workSystemPalette, jobsSystemPalette, walletSystemPalette, eBensSystemPalette, ehWorkDarkSystemPalette, ehWorkSystemPalette, ehJobsSystemPalette, ehWorkShadowPalette, ehJobsShadowPalette, ehWorkDarkShadowPalette, Accordion, Alert, AppCue, Attachment, Avatar, useAvatarColors, Badge, BottomNavigation, BottomSheet, Box, Button, Calendar, Card, Chart, Carousel, Chip, Collapse, Checkbox, ContentNavigator, DatePicker, Divider, Drawer, Empty, Error, FAB, FlatListWithFAB, Icon, Illustration, type IllustrationName, IllustrationList, Image, HeroDesignProvider, MapPin, List, PinInput, Progress, Portal, PageControl, Skeleton, Slider, Spinner, Swipeable, Radio, Search, SegmentedControl, ScrollViewWithFAB, SectionHeading, SectionListWithFAB, Select, Success, Switch, Tabs, Tag, TextInput, TimePicker, Toast, Toolbar, Typography, Rate, RefreshControl, RichTextEditor, FloatingIsland, LocaleProvider, FilterTrigger, InlineLoader, type InlineLoaderProps, styled, };
|
|
66
|
+
export { theme, getTheme, useTheme, scale, ThemeProvider, ThemeSwitcher, withTheme, swagSystemPalette, swagLightSystemPalette, swagLightJobsSystemPalette, swagDarkSystemPalette, workSystemPalette, jobsSystemPalette, walletSystemPalette, eBensSystemPalette, ehWorkDarkSystemPalette, ehWorkSystemPalette, ehJobsSystemPalette, ehWorkShadowPalette, ehJobsShadowPalette, ehWorkDarkShadowPalette, Accordion, Alert, AppCue, Attachment, Avatar, useAvatarColors, Badge, BottomNavigation, BottomSheet, Box, Button, Calendar, Card, Chart, Carousel, Chip, Collapse, Checkbox, ContentNavigator, DatePicker, Divider, Drawer, Empty, Error, FAB, FlatListWithFAB, Icon, Illustration, type IllustrationName, IllustrationList, Image, HeroDesignProvider, MapPin, List, PinInput, Progress, Portal, PageControl, Skeleton, Slider, Spinner, Swipeable, Radio, Search, SegmentedControl, ScrollViewWithFAB, SectionHeading, SectionList, SectionListWithFAB, Select, Success, Switch, Tabs, Tag, TextInput, TimePicker, Toast, Toolbar, Typography, Rate, RefreshControl, RichTextEditor, FloatingIsland, LocaleProvider, FilterTrigger, InlineLoader, type InlineLoaderProps, styled, };
|
|
66
67
|
export * from './types';
|
|
67
68
|
export type { ShadowPalette };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { GlobalTheme } from '../global';
|
|
2
|
+
declare const getSectionListTheme: (theme: GlobalTheme) => {
|
|
3
|
+
colors: {
|
|
4
|
+
groupBackground: string;
|
|
5
|
+
};
|
|
6
|
+
radii: {
|
|
7
|
+
group: number;
|
|
8
|
+
};
|
|
9
|
+
space: {
|
|
10
|
+
marginHorizontal: {
|
|
11
|
+
none: number;
|
|
12
|
+
xsmall: number;
|
|
13
|
+
small: number;
|
|
14
|
+
medium: number;
|
|
15
|
+
large: number;
|
|
16
|
+
xlarge: number;
|
|
17
|
+
};
|
|
18
|
+
sectionSpacing: number;
|
|
19
|
+
sectionSpacingCompact: number;
|
|
20
|
+
headingPaddingLeft: number;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
export default getSectionListTheme;
|
|
@@ -32,6 +32,7 @@ import getRateTheme from './components/rate';
|
|
|
32
32
|
import getRefreshControlTheme from './components/refreshControl';
|
|
33
33
|
import getRichTextEditorTheme from './components/richTextEditor';
|
|
34
34
|
import getSectionHeadingTheme from './components/sectionHeading';
|
|
35
|
+
import getSectionListTheme from './components/sectionList';
|
|
35
36
|
import getSelectTheme from './components/select';
|
|
36
37
|
import getSkeletonTheme from './components/skeleton';
|
|
37
38
|
import getSliderTheme from './components/slider';
|
|
@@ -97,6 +98,7 @@ type Theme = GlobalTheme & {
|
|
|
97
98
|
richTextEditor: ReturnType<typeof getRichTextEditorTheme>;
|
|
98
99
|
search: ReturnType<typeof getSearchTheme>;
|
|
99
100
|
sectionHeading: ReturnType<typeof getSectionHeadingTheme>;
|
|
101
|
+
sectionList: ReturnType<typeof getSectionListTheme>;
|
|
100
102
|
select: ReturnType<typeof getSelectTheme>;
|
|
101
103
|
skeleton: ReturnType<typeof getSkeletonTheme>;
|
|
102
104
|
slider: ReturnType<typeof getSliderTheme>;
|
package/types/types.d.ts
CHANGED
|
@@ -87,3 +87,4 @@ export type { SkeletonProps } from './components/Skeleton';
|
|
|
87
87
|
export type { SpinnerProps } from './components/Spinner';
|
|
88
88
|
export type { SwitchProps } from './components/Switch';
|
|
89
89
|
export type { TagProps } from './components/Tag';
|
|
90
|
+
export type { SectionListProps } from './components/SectionList';
|