@ankhorage/surface 9.4.11 → 9.4.12
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/README.md +1 -1
- package/dist/features/layout/adapters/inbound/ScrollView.d.ts.map +1 -1
- package/dist/features/layout/adapters/inbound/ScrollView.js +9 -3
- package/dist/features/layout/adapters/inbound/ScrollView.js.map +1 -1
- package/dist/types/layout.d.ts +4 -0
- package/dist/types/layout.d.ts.map +1 -1
- package/dist/types/layout.js.map +1 -1
- package/package.json +1 -1
- package/src/features/layout/adapters/inbound/ScrollView.test.tsx +60 -0
- package/src/features/layout/adapters/inbound/ScrollView.tsx +28 -2
- package/src/types/layout.ts +4 -0
- package/src/webAcceptance.test.tsx +19 -0
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
# @ankhorage/surface
|
|
5
5
|
|
|
6
|
-
         
|
|
7
7
|
|
|
8
8
|
Cross-platform UI foundation for React Native and React Native Web. Provides theming, layout primitives, and core building blocks for modern apps.
|
|
9
9
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScrollView.d.ts","sourceRoot":"","sources":["../../../../../src/features/layout/adapters/inbound/ScrollView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ScrollView.d.ts","sourceRoot":"","sources":["../../../../../src/features/layout/adapters/inbound/ScrollView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAIhE,uFAAuF;AACvF,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,qBAiChD"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { ScrollView as ReactNativeScrollView } from 'react-native';
|
|
2
|
+
import { RefreshControl, ScrollView as ReactNativeScrollView, } from 'react-native';
|
|
3
3
|
import { useResponsiveRuntime } from '../../../../core/responsive';
|
|
4
4
|
import { resolveViewStyles } from '../../../../utils/resolveViewStyles';
|
|
5
5
|
import { useTheme } from '../../../theme/runtime';
|
|
@@ -11,17 +11,23 @@ export function ScrollView(props) {
|
|
|
11
11
|
const visual = splitVisualProps(spacing.rest);
|
|
12
12
|
const dimensions = splitDimensionProps(visual.rest);
|
|
13
13
|
const layout = splitLayoutProps(dimensions.rest);
|
|
14
|
-
const { children, contentContainerStyle, style, ...scrollProps } = layout.rest;
|
|
14
|
+
const { children, contentContainerStyle, style, refreshing, onRefresh, refreshControl: nativeRefreshControl, ...scrollProps } = layout.rest;
|
|
15
15
|
const resolved = resolveViewStyles(theme, breakpoint, {
|
|
16
16
|
...spacing.styleProps,
|
|
17
17
|
...visual.styleProps,
|
|
18
18
|
...dimensions.styleProps,
|
|
19
19
|
...layout.styleProps,
|
|
20
20
|
});
|
|
21
|
-
return (<ReactNativeScrollView {...scrollProps} contentContainerStyle={contentContainerStyle} style={[resolved, style]}>
|
|
21
|
+
return (<ReactNativeScrollView {...scrollProps} contentContainerStyle={contentContainerStyle} refreshControl={resolveRefreshControl({ nativeRefreshControl, onRefresh, refreshing })} style={[resolved, style]}>
|
|
22
22
|
{children}
|
|
23
23
|
</ReactNativeScrollView>);
|
|
24
24
|
}
|
|
25
|
+
/*** Creates the standard controlled React Native refresh control only when Surface refresh props are supplied. */
|
|
26
|
+
function resolveRefreshControl({ nativeRefreshControl, onRefresh, refreshing, }) {
|
|
27
|
+
if (onRefresh === undefined && refreshing === undefined)
|
|
28
|
+
return nativeRefreshControl;
|
|
29
|
+
return <RefreshControl onRefresh={onRefresh} refreshing={refreshing ?? false}/>;
|
|
30
|
+
}
|
|
25
31
|
/*** Splits spacing-aware Surface props from native ScrollView props. */
|
|
26
32
|
function splitSpacingProps(props) {
|
|
27
33
|
const { p, px, py, pt, pb, pl, pr, m, mx, my, mt, mb, ml, mr, gap, rowGap, columnGap, ...rest } = props;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScrollView.js","sourceRoot":"","sources":["../../../../../src/features/layout/adapters/inbound/ScrollView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,
|
|
1
|
+
{"version":3,"file":"ScrollView.js","sourceRoot":"","sources":["../../../../../src/features/layout/adapters/inbound/ScrollView.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport {\n RefreshControl,\n ScrollView as ReactNativeScrollView,\n type ScrollViewProps as ReactNativeScrollViewProps,\n} from 'react-native';\n\nimport { useResponsiveRuntime } from '../../../../core/responsive';\nimport type { ScrollViewProps } from '../../../../types/layout';\nimport { resolveViewStyles } from '../../../../utils/resolveViewStyles';\nimport { useTheme } from '../../../theme/runtime';\n\n/*** Renders the token-aware responsive Surface adapter for React Native ScrollView. */\nexport function ScrollView(props: ScrollViewProps) {\n const { theme } = useTheme();\n const { breakpoint } = useResponsiveRuntime();\n const spacing = splitSpacingProps(props);\n const visual = splitVisualProps(spacing.rest);\n const dimensions = splitDimensionProps(visual.rest);\n const layout = splitLayoutProps(dimensions.rest);\n const {\n children,\n contentContainerStyle,\n style,\n refreshing,\n onRefresh,\n refreshControl: nativeRefreshControl,\n ...scrollProps\n } = layout.rest;\n const resolved = resolveViewStyles(theme, breakpoint, {\n ...spacing.styleProps,\n ...visual.styleProps,\n ...dimensions.styleProps,\n ...layout.styleProps,\n });\n\n return (\n <ReactNativeScrollView\n {...scrollProps}\n contentContainerStyle={contentContainerStyle}\n refreshControl={resolveRefreshControl({ nativeRefreshControl, onRefresh, refreshing })}\n style={[resolved, style]}\n >\n {children}\n </ReactNativeScrollView>\n );\n}\n\n/*** Creates the standard controlled React Native refresh control only when Surface refresh props are supplied. */\nfunction resolveRefreshControl({\n nativeRefreshControl,\n onRefresh,\n refreshing,\n}: Pick<ScrollViewProps, 'onRefresh' | 'refreshing'> & {\n nativeRefreshControl: ReactNativeScrollViewProps['refreshControl'];\n}) {\n if (onRefresh === undefined && refreshing === undefined) return nativeRefreshControl;\n\n return <RefreshControl onRefresh={onRefresh} refreshing={refreshing ?? false} />;\n}\n\n/*** Splits spacing-aware Surface props from native ScrollView props. */\nfunction splitSpacingProps(props: ScrollViewProps) {\n const { p, px, py, pt, pb, pl, pr, m, mx, my, mt, mb, ml, mr, gap, rowGap, columnGap, ...rest } =\n props;\n return {\n rest,\n styleProps: { p, px, py, pt, pb, pl, pr, m, mx, my, mt, mb, ml, mr, gap, rowGap, columnGap },\n };\n}\n\n/*** Splits token-aware visual Surface props from native ScrollView props. */\nfunction splitVisualProps(props: ReturnType<typeof splitSpacingProps>['rest']) {\n const { bg, radius, borderWidth, borderColor, ...rest } = props;\n return { rest, styleProps: { bg, radius, borderWidth, borderColor } };\n}\n\n/*** Splits responsive dimension Surface props from native ScrollView props. */\nfunction splitDimensionProps(props: ReturnType<typeof splitVisualProps>['rest']) {\n const { width, height, minWidth, maxWidth, minHeight, maxHeight, ...rest } = props;\n return { rest, styleProps: { width, height, minWidth, maxWidth, minHeight, maxHeight } };\n}\n\n/*** Splits responsive flex and positioning Surface props from native ScrollView props. */\nfunction splitLayoutProps(props: ReturnType<typeof splitDimensionProps>['rest']) {\n const {\n flex,\n flexGrow,\n flexShrink,\n flexBasis,\n direction,\n align,\n justify,\n wrap,\n alignSelf,\n position,\n top,\n bottom,\n left,\n right,\n overflow,\n zIndex,\n opacity,\n ...rest\n } = props;\n return {\n rest,\n styleProps: {\n flex,\n flexGrow,\n flexShrink,\n flexBasis,\n direction,\n align,\n justify,\n wrap,\n alignSelf,\n position,\n top,\n bottom,\n left,\n right,\n overflow,\n zIndex,\n opacity,\n },\n };\n}\n"]}
|
package/dist/types/layout.d.ts
CHANGED
|
@@ -82,6 +82,10 @@ export interface GridProps extends Omit<ViewProps, 'children'> {
|
|
|
82
82
|
export interface ScrollViewProps extends ViewStyleProps, Omit<ReactNativeScrollViewProps, 'children' | 'contentContainerStyle' | 'style'> {
|
|
83
83
|
children?: React.ReactNode;
|
|
84
84
|
contentContainerStyle?: StyleProp<ViewStyle>;
|
|
85
|
+
/** Controlled visibility of the native refresh indicator. */
|
|
86
|
+
refreshing?: boolean;
|
|
87
|
+
/** Called by the native refresh control after a pull-to-refresh gesture. */
|
|
88
|
+
onRefresh?: () => void;
|
|
85
89
|
}
|
|
86
90
|
export {};
|
|
87
91
|
//# sourceMappingURL=layout.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../src/types/layout.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../src/types/layout.ts"],"names":[],"mappings":"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"}
|
package/dist/types/layout.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/types/layout.ts"],"names":[],"mappings":"","sourcesContent":["import type React from 'react';\nimport type {\n ScrollViewProps as ReactNativeScrollViewProps,\n StyleProp,\n ViewProps as ReactNativeViewProps,\n ViewStyle,\n} from 'react-native';\n\nimport type { Responsive } from '../core/responsive';\nimport type { SurfaceTheme } from './theme';\n\ntype SpaceToken = keyof SurfaceTheme['spacing'];\ntype RadiusToken = keyof SurfaceTheme['radii'];\ntype ColorToken = keyof SurfaceTheme['colors'];\ntype RadiusValue = number | RadiusToken;\n\nexport type SpaceValue = number | SpaceToken;\nexport type ColorValue = string | ColorToken;\n\nexport interface ViewStyleProps {\n p?: Responsive<SpaceValue>;\n px?: Responsive<SpaceValue>;\n py?: Responsive<SpaceValue>;\n pt?: Responsive<SpaceValue>;\n pb?: Responsive<SpaceValue>;\n pl?: Responsive<SpaceValue>;\n pr?: Responsive<SpaceValue>;\n m?: Responsive<SpaceValue>;\n mx?: Responsive<SpaceValue>;\n my?: Responsive<SpaceValue>;\n mt?: Responsive<SpaceValue>;\n mb?: Responsive<SpaceValue>;\n ml?: Responsive<SpaceValue>;\n mr?: Responsive<SpaceValue>;\n gap?: Responsive<SpaceValue>;\n rowGap?: Responsive<SpaceValue>;\n columnGap?: Responsive<SpaceValue>;\n bg?: Responsive<ColorValue>;\n radius?: Responsive<RadiusValue>;\n borderWidth?: Responsive<number>;\n borderColor?: Responsive<ColorValue>;\n width?: Responsive<number | string>;\n height?: Responsive<number | string>;\n minWidth?: Responsive<number | string>;\n maxWidth?: Responsive<number | string>;\n minHeight?: Responsive<number | string>;\n maxHeight?: Responsive<number | string>;\n flex?: Responsive<number>;\n flexGrow?: Responsive<number>;\n flexShrink?: Responsive<number>;\n flexBasis?: Responsive<number | string>;\n direction?: Responsive<'row' | 'column'>;\n align?: Responsive<'flex-start' | 'center' | 'flex-end' | 'stretch' | 'baseline'>;\n justify?: Responsive<\n 'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly'\n >;\n wrap?: Responsive<'nowrap' | 'wrap'>;\n alignSelf?: Responsive<ViewStyle['alignSelf']>;\n position?: Responsive<ViewStyle['position']>;\n top?: Responsive<number>;\n bottom?: Responsive<number>;\n left?: Responsive<number>;\n right?: Responsive<number>;\n overflow?: Responsive<ViewStyle['overflow']>;\n zIndex?: Responsive<number>;\n opacity?: Responsive<number>;\n style?: StyleProp<ViewStyle>;\n}\n\nexport interface ViewProps extends ViewStyleProps {\n accessibilityLabel?: ReactNativeViewProps['accessibilityLabel'];\n accessibilityLabelledBy?: ReactNativeViewProps['accessibilityLabelledBy'];\n accessibilityRole?: ReactNativeViewProps['accessibilityRole'];\n accessibilityState?: ReactNativeViewProps['accessibilityState'];\n accessible?: ReactNativeViewProps['accessible'];\n children?: React.ReactNode;\n nativeID?: ReactNativeViewProps['nativeID'];\n pointerEvents?: ReactNativeViewProps['pointerEvents'];\n testID?: string;\n}\n\nexport interface DividerProps extends Omit<ViewProps, 'bg' | 'height' | 'width'> {\n orientation?: 'horizontal' | 'vertical';\n color?: ColorValue;\n thickness?: number;\n}\n\nexport interface GridProps extends Omit<ViewProps, 'children'> {\n children?: React.ReactNode;\n cols?: Responsive<number>;\n gap?: Responsive<SpaceValue>;\n rowGap?: Responsive<SpaceValue>;\n colGap?: Responsive<SpaceValue>;\n minItemWidth?: Responsive<number>;\n}\n\nexport interface ScrollViewProps\n extends\n ViewStyleProps,\n Omit<ReactNativeScrollViewProps, 'children' | 'contentContainerStyle' | 'style'> {\n children?: React.ReactNode;\n contentContainerStyle?: StyleProp<ViewStyle>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/types/layout.ts"],"names":[],"mappings":"","sourcesContent":["import type React from 'react';\nimport type {\n ScrollViewProps as ReactNativeScrollViewProps,\n StyleProp,\n ViewProps as ReactNativeViewProps,\n ViewStyle,\n} from 'react-native';\n\nimport type { Responsive } from '../core/responsive';\nimport type { SurfaceTheme } from './theme';\n\ntype SpaceToken = keyof SurfaceTheme['spacing'];\ntype RadiusToken = keyof SurfaceTheme['radii'];\ntype ColorToken = keyof SurfaceTheme['colors'];\ntype RadiusValue = number | RadiusToken;\n\nexport type SpaceValue = number | SpaceToken;\nexport type ColorValue = string | ColorToken;\n\nexport interface ViewStyleProps {\n p?: Responsive<SpaceValue>;\n px?: Responsive<SpaceValue>;\n py?: Responsive<SpaceValue>;\n pt?: Responsive<SpaceValue>;\n pb?: Responsive<SpaceValue>;\n pl?: Responsive<SpaceValue>;\n pr?: Responsive<SpaceValue>;\n m?: Responsive<SpaceValue>;\n mx?: Responsive<SpaceValue>;\n my?: Responsive<SpaceValue>;\n mt?: Responsive<SpaceValue>;\n mb?: Responsive<SpaceValue>;\n ml?: Responsive<SpaceValue>;\n mr?: Responsive<SpaceValue>;\n gap?: Responsive<SpaceValue>;\n rowGap?: Responsive<SpaceValue>;\n columnGap?: Responsive<SpaceValue>;\n bg?: Responsive<ColorValue>;\n radius?: Responsive<RadiusValue>;\n borderWidth?: Responsive<number>;\n borderColor?: Responsive<ColorValue>;\n width?: Responsive<number | string>;\n height?: Responsive<number | string>;\n minWidth?: Responsive<number | string>;\n maxWidth?: Responsive<number | string>;\n minHeight?: Responsive<number | string>;\n maxHeight?: Responsive<number | string>;\n flex?: Responsive<number>;\n flexGrow?: Responsive<number>;\n flexShrink?: Responsive<number>;\n flexBasis?: Responsive<number | string>;\n direction?: Responsive<'row' | 'column'>;\n align?: Responsive<'flex-start' | 'center' | 'flex-end' | 'stretch' | 'baseline'>;\n justify?: Responsive<\n 'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around' | 'space-evenly'\n >;\n wrap?: Responsive<'nowrap' | 'wrap'>;\n alignSelf?: Responsive<ViewStyle['alignSelf']>;\n position?: Responsive<ViewStyle['position']>;\n top?: Responsive<number>;\n bottom?: Responsive<number>;\n left?: Responsive<number>;\n right?: Responsive<number>;\n overflow?: Responsive<ViewStyle['overflow']>;\n zIndex?: Responsive<number>;\n opacity?: Responsive<number>;\n style?: StyleProp<ViewStyle>;\n}\n\nexport interface ViewProps extends ViewStyleProps {\n accessibilityLabel?: ReactNativeViewProps['accessibilityLabel'];\n accessibilityLabelledBy?: ReactNativeViewProps['accessibilityLabelledBy'];\n accessibilityRole?: ReactNativeViewProps['accessibilityRole'];\n accessibilityState?: ReactNativeViewProps['accessibilityState'];\n accessible?: ReactNativeViewProps['accessible'];\n children?: React.ReactNode;\n nativeID?: ReactNativeViewProps['nativeID'];\n pointerEvents?: ReactNativeViewProps['pointerEvents'];\n testID?: string;\n}\n\nexport interface DividerProps extends Omit<ViewProps, 'bg' | 'height' | 'width'> {\n orientation?: 'horizontal' | 'vertical';\n color?: ColorValue;\n thickness?: number;\n}\n\nexport interface GridProps extends Omit<ViewProps, 'children'> {\n children?: React.ReactNode;\n cols?: Responsive<number>;\n gap?: Responsive<SpaceValue>;\n rowGap?: Responsive<SpaceValue>;\n colGap?: Responsive<SpaceValue>;\n minItemWidth?: Responsive<number>;\n}\n\nexport interface ScrollViewProps\n extends\n ViewStyleProps,\n Omit<ReactNativeScrollViewProps, 'children' | 'contentContainerStyle' | 'style'> {\n children?: React.ReactNode;\n contentContainerStyle?: StyleProp<ViewStyle>;\n /** Controlled visibility of the native refresh indicator. */\n refreshing?: boolean;\n /** Called by the native refresh control after a pull-to-refresh gesture. */\n onRefresh?: () => void;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { expect, mock, test } from 'bun:test';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { renderToString } from 'react-dom/server';
|
|
4
|
+
import * as ReactNativeWeb from 'react-native-web';
|
|
5
|
+
|
|
6
|
+
type RecordedScrollViewProps = Readonly<Record<string, unknown>>;
|
|
7
|
+
|
|
8
|
+
const recordedScrollViewProps: RecordedScrollViewProps[] = [];
|
|
9
|
+
|
|
10
|
+
await mock.module('react-native', () => ({
|
|
11
|
+
...ReactNativeWeb,
|
|
12
|
+
RefreshControl: () => null,
|
|
13
|
+
ScrollView: (props: RecordedScrollViewProps) => {
|
|
14
|
+
recordedScrollViewProps.push(props);
|
|
15
|
+
return null;
|
|
16
|
+
},
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
const { ScrollView } = await import('./ScrollView');
|
|
20
|
+
const { ThemeProvider } = await import('../../../theme/runtime');
|
|
21
|
+
|
|
22
|
+
/*** Renders Surface ScrollView under the production theme boundary and captures native props. */
|
|
23
|
+
function renderScrollView(props: React.ComponentProps<typeof ScrollView>) {
|
|
24
|
+
recordedScrollViewProps.splice(0);
|
|
25
|
+
renderToString(
|
|
26
|
+
<ThemeProvider>
|
|
27
|
+
<ScrollView {...props} />
|
|
28
|
+
</ThemeProvider>,
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const renderedProps = recordedScrollViewProps.at(-1);
|
|
32
|
+
if (renderedProps === undefined) throw new Error('ScrollView did not render.');
|
|
33
|
+
return renderedProps;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
test('creates a controlled native RefreshControl from Surface refresh props', () => {
|
|
37
|
+
const onRefresh = () => undefined;
|
|
38
|
+
const rendered = renderScrollView({ onRefresh, refreshing: true });
|
|
39
|
+
const refreshControl = rendered.refreshControl as React.ReactElement<{
|
|
40
|
+
onRefresh?: () => void;
|
|
41
|
+
refreshing: boolean;
|
|
42
|
+
}>;
|
|
43
|
+
|
|
44
|
+
expect(refreshControl.type).toBeDefined();
|
|
45
|
+
expect(refreshControl.props).toEqual({ onRefresh, refreshing: true });
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('defaults a requested refresh control to its inactive controlled state', () => {
|
|
49
|
+
const rendered = renderScrollView({ onRefresh: () => undefined });
|
|
50
|
+
const refreshControl = rendered.refreshControl as React.ReactElement<{ refreshing: boolean }>;
|
|
51
|
+
|
|
52
|
+
expect(refreshControl.props.refreshing).toBe(false);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('preserves a caller-provided native refresh control when Surface refresh props are absent', () => {
|
|
56
|
+
const nativeRefreshControl = <ReactNativeWeb.View />;
|
|
57
|
+
const rendered = renderScrollView({ refreshControl: nativeRefreshControl });
|
|
58
|
+
|
|
59
|
+
expect(rendered.refreshControl).toBe(nativeRefreshControl);
|
|
60
|
+
});
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
RefreshControl,
|
|
4
|
+
ScrollView as ReactNativeScrollView,
|
|
5
|
+
type ScrollViewProps as ReactNativeScrollViewProps,
|
|
6
|
+
} from 'react-native';
|
|
3
7
|
|
|
4
8
|
import { useResponsiveRuntime } from '../../../../core/responsive';
|
|
5
9
|
import type { ScrollViewProps } from '../../../../types/layout';
|
|
@@ -14,7 +18,15 @@ export function ScrollView(props: ScrollViewProps) {
|
|
|
14
18
|
const visual = splitVisualProps(spacing.rest);
|
|
15
19
|
const dimensions = splitDimensionProps(visual.rest);
|
|
16
20
|
const layout = splitLayoutProps(dimensions.rest);
|
|
17
|
-
const {
|
|
21
|
+
const {
|
|
22
|
+
children,
|
|
23
|
+
contentContainerStyle,
|
|
24
|
+
style,
|
|
25
|
+
refreshing,
|
|
26
|
+
onRefresh,
|
|
27
|
+
refreshControl: nativeRefreshControl,
|
|
28
|
+
...scrollProps
|
|
29
|
+
} = layout.rest;
|
|
18
30
|
const resolved = resolveViewStyles(theme, breakpoint, {
|
|
19
31
|
...spacing.styleProps,
|
|
20
32
|
...visual.styleProps,
|
|
@@ -26,6 +38,7 @@ export function ScrollView(props: ScrollViewProps) {
|
|
|
26
38
|
<ReactNativeScrollView
|
|
27
39
|
{...scrollProps}
|
|
28
40
|
contentContainerStyle={contentContainerStyle}
|
|
41
|
+
refreshControl={resolveRefreshControl({ nativeRefreshControl, onRefresh, refreshing })}
|
|
29
42
|
style={[resolved, style]}
|
|
30
43
|
>
|
|
31
44
|
{children}
|
|
@@ -33,6 +46,19 @@ export function ScrollView(props: ScrollViewProps) {
|
|
|
33
46
|
);
|
|
34
47
|
}
|
|
35
48
|
|
|
49
|
+
/*** Creates the standard controlled React Native refresh control only when Surface refresh props are supplied. */
|
|
50
|
+
function resolveRefreshControl({
|
|
51
|
+
nativeRefreshControl,
|
|
52
|
+
onRefresh,
|
|
53
|
+
refreshing,
|
|
54
|
+
}: Pick<ScrollViewProps, 'onRefresh' | 'refreshing'> & {
|
|
55
|
+
nativeRefreshControl: ReactNativeScrollViewProps['refreshControl'];
|
|
56
|
+
}) {
|
|
57
|
+
if (onRefresh === undefined && refreshing === undefined) return nativeRefreshControl;
|
|
58
|
+
|
|
59
|
+
return <RefreshControl onRefresh={onRefresh} refreshing={refreshing ?? false} />;
|
|
60
|
+
}
|
|
61
|
+
|
|
36
62
|
/*** Splits spacing-aware Surface props from native ScrollView props. */
|
|
37
63
|
function splitSpacingProps(props: ScrollViewProps) {
|
|
38
64
|
const { p, px, py, pt, pb, pl, pr, m, mx, my, mt, mb, ml, mr, gap, rowGap, columnGap, ...rest } =
|
package/src/types/layout.ts
CHANGED
|
@@ -100,4 +100,8 @@ export interface ScrollViewProps
|
|
|
100
100
|
Omit<ReactNativeScrollViewProps, 'children' | 'contentContainerStyle' | 'style'> {
|
|
101
101
|
children?: React.ReactNode;
|
|
102
102
|
contentContainerStyle?: StyleProp<ViewStyle>;
|
|
103
|
+
/** Controlled visibility of the native refresh indicator. */
|
|
104
|
+
refreshing?: boolean;
|
|
105
|
+
/** Called by the native refresh control after a pull-to-refresh gesture. */
|
|
106
|
+
onRefresh?: () => void;
|
|
103
107
|
}
|
|
@@ -165,3 +165,22 @@ test('RN Web 0.21 renders keyboard-safe content through the Surface layout bound
|
|
|
165
165
|
expect(markup).toContain('data-testid="keyboard-safe"');
|
|
166
166
|
expect(markup).toContain('Keyboard-safe content');
|
|
167
167
|
});
|
|
168
|
+
|
|
169
|
+
test('RN Web renders controlled refresh state without simulating a native pull gesture', () => {
|
|
170
|
+
const refreshSignals: undefined[] = [];
|
|
171
|
+
const markup = renderToString(
|
|
172
|
+
<ThemeProvider>
|
|
173
|
+
<ScrollView
|
|
174
|
+
onRefresh={() => refreshSignals.push(undefined)}
|
|
175
|
+
refreshing
|
|
176
|
+
testID="refreshable-scroll-view"
|
|
177
|
+
>
|
|
178
|
+
<ReactNativeWeb.Text>refreshable content</ReactNativeWeb.Text>
|
|
179
|
+
</ScrollView>
|
|
180
|
+
</ThemeProvider>,
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
expect(markup).toContain('data-testid="refreshable-scroll-view"');
|
|
184
|
+
expect(markup).toContain('refreshable content');
|
|
185
|
+
expect(refreshSignals).toEqual([]);
|
|
186
|
+
});
|