bootstrap-rn 0.4.3 → 0.4.4
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/lib/module/components/close/CloseButton.js +1 -1
- package/lib/module/components/close/CloseButton.js.map +1 -1
- package/lib/module/components/forms/internals/FormCheckInputNative.js +1 -1
- package/lib/module/components/forms/internals/FormCheckInputNative.js.map +1 -1
- package/lib/module/components/forms/internals/FormCheckInputWeb.js +4 -2
- package/lib/module/components/forms/internals/FormCheckInputWeb.js.map +1 -1
- package/lib/module/components/forms/internals/PickerNative.js +1 -1
- package/lib/module/components/forms/internals/PickerNative.js.map +1 -1
- package/lib/module/components/forms/internals/PickerWeb.js +5 -2
- package/lib/module/components/forms/internals/PickerWeb.js.map +1 -1
- package/lib/module/components/navbar/NavbarToggler.js +1 -1
- package/lib/module/components/navbar/NavbarToggler.js.map +1 -1
- package/lib/module/hooks/useBackground.js +4 -78
- package/lib/module/hooks/useBackground.js.map +1 -1
- package/lib/module/hooks/{useBackground.native.js → useBackgroundNative.js} +2 -2
- package/lib/module/hooks/useBackgroundNative.js.map +1 -0
- package/lib/module/hooks/useBackgroundWeb.js +81 -0
- package/lib/module/hooks/useBackgroundWeb.js.map +1 -0
- package/lib/typescript/components/forms/internals/FormCheckInputWeb.d.ts.map +1 -1
- package/lib/typescript/components/forms/internals/PickerNative.d.ts.map +1 -1
- package/lib/typescript/components/forms/internals/PickerWeb.d.ts.map +1 -1
- package/lib/typescript/hooks/useBackground.d.ts +4 -5
- package/lib/typescript/hooks/useBackground.d.ts.map +1 -1
- package/lib/typescript/hooks/{useBackground.native.d.ts → useBackgroundNative.d.ts} +2 -2
- package/lib/typescript/hooks/useBackgroundNative.d.ts.map +1 -0
- package/lib/typescript/hooks/useBackgroundWeb.d.ts +6 -0
- package/lib/typescript/hooks/useBackgroundWeb.d.ts.map +1 -0
- package/package.json +3 -3
- package/src/components/forms/internals/FormCheckInputWeb.tsx +79 -78
- package/src/components/forms/internals/PickerNative.tsx +3 -2
- package/src/components/forms/internals/PickerWeb.tsx +85 -78
- package/src/hooks/useBackground.tsx +4 -122
- package/src/hooks/{useBackground.native.tsx → useBackgroundNative.tsx} +1 -1
- package/src/hooks/useBackgroundWeb.tsx +123 -0
- package/src/style/transform/index.ts +245 -245
- package/lib/module/hooks/useBackground.native.js.map +0 -1
- package/lib/typescript/hooks/useBackground.native.d.ts.map +0 -1
|
@@ -1,78 +1,79 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
// @ts-expect-error import is available
|
|
4
|
-
unstable_createElement as createElement,
|
|
5
|
-
StyleSheet,
|
|
6
|
-
ViewStyle,
|
|
7
|
-
} from 'react-native';
|
|
8
|
-
import useBackground from '../../../hooks/useBackground';
|
|
9
|
-
import type { PressableRef } from '../../Pressable';
|
|
10
|
-
import type { FormCheckInputProps } from '../FormCheckInput';
|
|
11
|
-
|
|
12
|
-
export interface FormCheckInputWebProps extends FormCheckInputProps {
|
|
13
|
-
style: ViewStyle[];
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const styles = StyleSheet.create({
|
|
17
|
-
reboot: {
|
|
18
|
-
flexShrink: 0,
|
|
19
|
-
margin: 0,
|
|
20
|
-
},
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
type InputProps = {
|
|
24
|
-
style?: ViewStyle[];
|
|
25
|
-
type: 'checkbox' | 'radio';
|
|
26
|
-
checked: boolean;
|
|
27
|
-
onChange: () => void;
|
|
28
|
-
onFocus: () => void;
|
|
29
|
-
onBlur: () => void;
|
|
30
|
-
disabled: boolean;
|
|
31
|
-
id?: string;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
35
|
-
({ style, ...props }, ref) =>
|
|
36
|
-
createElement('input', { ...props, ref, style: [styles.reboot, style] }),
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
const FormCheckInputWeb = React.forwardRef<
|
|
40
|
-
PressableRef,
|
|
41
|
-
FormCheckInputWebProps
|
|
42
|
-
>((props, ref) => {
|
|
43
|
-
const {
|
|
44
|
-
type,
|
|
45
|
-
value,
|
|
46
|
-
onValueChange: handleValueChange,
|
|
47
|
-
onFocus = () => {},
|
|
48
|
-
onBlur = () => {},
|
|
49
|
-
disabled = false,
|
|
50
|
-
style,
|
|
51
|
-
id,
|
|
52
|
-
autoFocus,
|
|
53
|
-
} = props;
|
|
54
|
-
|
|
55
|
-
const inputBackground = useBackground(style);
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<Input
|
|
59
|
-
// @ts-expect-error We need to create a native ref here in the future.
|
|
60
|
-
ref={ref}
|
|
61
|
-
type={type === 'switch' ? 'checkbox' : type}
|
|
62
|
-
checked={value}
|
|
63
|
-
onChange={() => {
|
|
64
|
-
if (handleValueChange) handleValueChange(!value);
|
|
65
|
-
}}
|
|
66
|
-
onFocus={onFocus}
|
|
67
|
-
onBlur={onBlur}
|
|
68
|
-
disabled={disabled}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
// @ts-expect-error import is available
|
|
4
|
+
unstable_createElement as createElement,
|
|
5
|
+
StyleSheet,
|
|
6
|
+
ViewStyle,
|
|
7
|
+
} from 'react-native';
|
|
8
|
+
import useBackground from '../../../hooks/useBackground';
|
|
9
|
+
import type { PressableRef } from '../../Pressable';
|
|
10
|
+
import type { FormCheckInputProps } from '../FormCheckInput';
|
|
11
|
+
|
|
12
|
+
export interface FormCheckInputWebProps extends FormCheckInputProps {
|
|
13
|
+
style: ViewStyle[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const styles = StyleSheet.create({
|
|
17
|
+
reboot: {
|
|
18
|
+
flexShrink: 0,
|
|
19
|
+
margin: 0,
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
type InputProps = {
|
|
24
|
+
style?: ViewStyle[];
|
|
25
|
+
type: 'checkbox' | 'radio';
|
|
26
|
+
checked: boolean;
|
|
27
|
+
onChange: () => void;
|
|
28
|
+
onFocus: () => void;
|
|
29
|
+
onBlur: () => void;
|
|
30
|
+
disabled: boolean;
|
|
31
|
+
id?: string;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
35
|
+
({ style, ...props }, ref) =>
|
|
36
|
+
createElement('input', { ...props, ref, style: [styles.reboot, style] }),
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const FormCheckInputWeb = React.forwardRef<
|
|
40
|
+
PressableRef,
|
|
41
|
+
FormCheckInputWebProps
|
|
42
|
+
>((props, ref) => {
|
|
43
|
+
const {
|
|
44
|
+
type,
|
|
45
|
+
value,
|
|
46
|
+
onValueChange: handleValueChange,
|
|
47
|
+
onFocus = () => {},
|
|
48
|
+
onBlur = () => {},
|
|
49
|
+
disabled = false,
|
|
50
|
+
style,
|
|
51
|
+
id,
|
|
52
|
+
autoFocus,
|
|
53
|
+
} = props;
|
|
54
|
+
|
|
55
|
+
const inputBackground = useBackground(style);
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<Input
|
|
59
|
+
// @ts-expect-error We need to create a native ref here in the future.
|
|
60
|
+
ref={ref}
|
|
61
|
+
type={type === 'switch' ? 'checkbox' : type}
|
|
62
|
+
checked={value}
|
|
63
|
+
onChange={() => {
|
|
64
|
+
if (handleValueChange) handleValueChange(!value);
|
|
65
|
+
}}
|
|
66
|
+
onFocus={onFocus}
|
|
67
|
+
onBlur={onBlur}
|
|
68
|
+
disabled={disabled}
|
|
69
|
+
// @ts-expect-error inputBackground.style should be a ViewStyle here.
|
|
70
|
+
style={inputBackground.style}
|
|
71
|
+
id={id}
|
|
72
|
+
autoFocus={autoFocus}
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
FormCheckInputWeb.displayName = 'FormCheckInputWeb';
|
|
78
|
+
|
|
79
|
+
export default FormCheckInputWeb;
|
|
@@ -14,7 +14,6 @@ import Offcanvas from '../../offcanvas/Offcanvas';
|
|
|
14
14
|
import useBackground from '../../../hooks/useBackground';
|
|
15
15
|
import PickerNativeContext from './PickerNativeContext';
|
|
16
16
|
import type { PickerProps, MenuComponentProps } from '../Picker';
|
|
17
|
-
import type { BaseStyle } from '../../../types';
|
|
18
17
|
import type { PickerItemProps } from '../PickerItem';
|
|
19
18
|
|
|
20
19
|
export interface PickerNativeProps extends PickerProps {
|
|
@@ -50,7 +49,9 @@ const textStyleKeys = [
|
|
|
50
49
|
'writingDirection',
|
|
51
50
|
];
|
|
52
51
|
|
|
53
|
-
const extractTextStyles = (
|
|
52
|
+
const extractTextStyles = (
|
|
53
|
+
style: ReturnType<typeof useBackground>['style'],
|
|
54
|
+
) => {
|
|
54
55
|
const flattenedStyle = StyleUtils.flatten(style);
|
|
55
56
|
const textStyles: { [key: string]: string } = {};
|
|
56
57
|
|
|
@@ -1,78 +1,85 @@
|
|
|
1
|
-
import React, { useMemo, forwardRef } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
// @ts-expect-error web only import
|
|
4
|
-
Picker as BasePicker,
|
|
5
|
-
StyleSheet as StyleUtils,
|
|
6
|
-
TextStyle,
|
|
7
|
-
} from 'react-native';
|
|
8
|
-
import useBackground from '../../../hooks/useBackground';
|
|
9
|
-
import PickerWebContext from './PickerWebContext';
|
|
10
|
-
import type { PickerProps } from '../Picker';
|
|
11
|
-
import type { PressableRef } from '../../Pressable';
|
|
12
|
-
|
|
13
|
-
interface PickerWebProps extends PickerProps {
|
|
14
|
-
style: TextStyle[];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const PLACEHOLDER = '__PLACEHOLDER__';
|
|
18
|
-
|
|
19
|
-
const getOptionStyle = (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
72
|
-
{
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
1
|
+
import React, { useMemo, forwardRef } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
// @ts-expect-error web only import
|
|
4
|
+
Picker as BasePicker,
|
|
5
|
+
StyleSheet as StyleUtils,
|
|
6
|
+
TextStyle,
|
|
7
|
+
} from 'react-native';
|
|
8
|
+
import useBackground from '../../../hooks/useBackground';
|
|
9
|
+
import PickerWebContext from './PickerWebContext';
|
|
10
|
+
import type { PickerProps } from '../Picker';
|
|
11
|
+
import type { PressableRef } from '../../Pressable';
|
|
12
|
+
|
|
13
|
+
interface PickerWebProps extends PickerProps {
|
|
14
|
+
style: TextStyle[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const PLACEHOLDER = '__PLACEHOLDER__';
|
|
18
|
+
|
|
19
|
+
const getOptionStyle = (
|
|
20
|
+
style: ReturnType<typeof useBackground>['style'],
|
|
21
|
+
showPlaceholder: boolean,
|
|
22
|
+
) => {
|
|
23
|
+
if (!showPlaceholder) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const flattenedStyle = StyleUtils.flatten(style);
|
|
28
|
+
|
|
29
|
+
if ('color' in flattenedStyle && flattenedStyle.color !== undefined) {
|
|
30
|
+
return flattenedStyle.color;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return null;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const PickerWeb = forwardRef<PressableRef, PickerWebProps>((props, ref) => {
|
|
37
|
+
const {
|
|
38
|
+
children,
|
|
39
|
+
selectedValue,
|
|
40
|
+
onValueChange = () => {},
|
|
41
|
+
onFocus = () => {},
|
|
42
|
+
onBlur = () => {},
|
|
43
|
+
placeholder,
|
|
44
|
+
placeholderTextColor,
|
|
45
|
+
disabled,
|
|
46
|
+
style,
|
|
47
|
+
...elementProps
|
|
48
|
+
} = props;
|
|
49
|
+
|
|
50
|
+
const background = useBackground(style);
|
|
51
|
+
|
|
52
|
+
const showPlaceholder = selectedValue === undefined || selectedValue === null;
|
|
53
|
+
|
|
54
|
+
const contextValue = useMemo(
|
|
55
|
+
() => ({
|
|
56
|
+
optionColor: getOptionStyle(background.style, showPlaceholder),
|
|
57
|
+
}),
|
|
58
|
+
[background, showPlaceholder],
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<BasePicker
|
|
63
|
+
{...elementProps}
|
|
64
|
+
ref={ref}
|
|
65
|
+
selectedValue={showPlaceholder ? PLACEHOLDER : selectedValue}
|
|
66
|
+
onValueChange={onValueChange}
|
|
67
|
+
onFocus={onFocus}
|
|
68
|
+
onBlur={onBlur}
|
|
69
|
+
disabled={disabled}
|
|
70
|
+
style={[
|
|
71
|
+
background.style,
|
|
72
|
+
showPlaceholder && { color: placeholderTextColor },
|
|
73
|
+
]}
|
|
74
|
+
>
|
|
75
|
+
<option value={PLACEHOLDER} disabled hidden>
|
|
76
|
+
{placeholder}
|
|
77
|
+
</option>
|
|
78
|
+
<PickerWebContext.Provider value={contextValue}>
|
|
79
|
+
{children}
|
|
80
|
+
</PickerWebContext.Provider>
|
|
81
|
+
</BasePicker>
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
export default PickerWeb;
|
|
@@ -1,123 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { Platform } from 'react-native';
|
|
2
|
+
import useBackgroundWeb from './useBackgroundWeb';
|
|
3
|
+
import useBackgroundNative from './useBackgroundNative';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
type PositionX = 'center' | 'left' | 'right';
|
|
6
|
-
type PositionY = 'center' | 'top' | 'bottom';
|
|
7
|
-
|
|
8
|
-
type BackgroundStyle = BaseStyle & {
|
|
9
|
-
backgroundSize?:
|
|
10
|
-
| 'contain'
|
|
11
|
-
| 'cover'
|
|
12
|
-
| string
|
|
13
|
-
| number
|
|
14
|
-
| { width: 'auto' | number; height: 'auto' | number };
|
|
15
|
-
backgroundPosition?: Position;
|
|
16
|
-
backgroundPositionX?:
|
|
17
|
-
| PositionX
|
|
18
|
-
| { position: PositionX; offset: string | number };
|
|
19
|
-
backgroundPositionY?:
|
|
20
|
-
| PositionY
|
|
21
|
-
| { position: PositionY; offset: string | number };
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
type PositionValue = {
|
|
25
|
-
positionX: PositionX;
|
|
26
|
-
offsetX: string | number;
|
|
27
|
-
positionY: PositionY;
|
|
28
|
-
offsetY: string | number;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const styles = StyleSheet.create({
|
|
32
|
-
reset: {
|
|
33
|
-
// Background repeat is not supported on native yet.
|
|
34
|
-
// @ts-expect-error web only style
|
|
35
|
-
backgroundRepeat: 'no-repeat',
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
const normalizeValue = (value: 'auto' | number | string) =>
|
|
40
|
-
typeof value === 'number' && value !== 0 ? `${value}px` : value;
|
|
41
|
-
|
|
42
|
-
const resolveBackgroundSize = (style: BackgroundStyle) => {
|
|
43
|
-
const { backgroundSize } = style;
|
|
44
|
-
|
|
45
|
-
if (typeof backgroundSize !== 'object') {
|
|
46
|
-
return backgroundSize;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const { width = 'auto', height = 'auto' } = backgroundSize;
|
|
50
|
-
|
|
51
|
-
return `${normalizeValue(width)} ${normalizeValue(height)}`;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const resolveBackgroundPosition = (style: BackgroundStyle) => {
|
|
55
|
-
const { backgroundPosition, backgroundPositionX, backgroundPositionY } =
|
|
56
|
-
style;
|
|
57
|
-
|
|
58
|
-
if (!backgroundPosition && !backgroundPositionX && !backgroundPositionY) {
|
|
59
|
-
return null;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const value: PositionValue = {
|
|
63
|
-
positionX:
|
|
64
|
-
backgroundPosition === 'center' || backgroundPosition === 'right'
|
|
65
|
-
? backgroundPosition
|
|
66
|
-
: 'left',
|
|
67
|
-
offsetX: 0,
|
|
68
|
-
positionY:
|
|
69
|
-
backgroundPosition === 'center' || backgroundPosition === 'bottom'
|
|
70
|
-
? backgroundPosition
|
|
71
|
-
: 'top',
|
|
72
|
-
offsetY: 0,
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
if (backgroundPositionX) {
|
|
76
|
-
const { position: positionX = 'left', offset: offsetX = 0 } =
|
|
77
|
-
typeof backgroundPositionX === 'object'
|
|
78
|
-
? backgroundPositionX
|
|
79
|
-
: { position: backgroundPositionX };
|
|
80
|
-
|
|
81
|
-
value.positionX = positionX;
|
|
82
|
-
value.offsetX = normalizeValue(offsetX);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
if (backgroundPositionY) {
|
|
86
|
-
const { position: positionY = 'top', offset: offsetY = 0 } =
|
|
87
|
-
typeof backgroundPositionY === 'object'
|
|
88
|
-
? backgroundPositionY
|
|
89
|
-
: { position: backgroundPositionY };
|
|
90
|
-
|
|
91
|
-
value.positionY = positionY;
|
|
92
|
-
value.offsetY = normalizeValue(offsetY);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const valueX = value.offsetX
|
|
96
|
-
? `${value.positionX} ${value.offsetX}`
|
|
97
|
-
: value.positionX;
|
|
98
|
-
const valueY = value.offsetY
|
|
99
|
-
? `${value.positionY} ${value.offsetY}`
|
|
100
|
-
: value.positionY;
|
|
101
|
-
|
|
102
|
-
return `${valueX} ${valueY}`;
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
export default function useBackground(style: BaseStyle[]) {
|
|
106
|
-
const flattenedStyle = StyleSheet.flatten(style);
|
|
107
|
-
|
|
108
|
-
const backgroundStyle: BaseStyle = {
|
|
109
|
-
// Transform background size
|
|
110
|
-
// @ts-expect-error web only style
|
|
111
|
-
backgroundSize: resolveBackgroundSize(flattenedStyle),
|
|
112
|
-
// Workaround, because some browsers do not support two-value syntax:
|
|
113
|
-
// https://developer.mozilla.org/en-US/docs/Web/CSS/background-position-x#browser_compatibility
|
|
114
|
-
backgroundPositionX: null,
|
|
115
|
-
backgroundPositionY: null,
|
|
116
|
-
backgroundPosition: resolveBackgroundPosition(flattenedStyle),
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
return {
|
|
120
|
-
style: [flattenedStyle, styles.reset, backgroundStyle],
|
|
121
|
-
element: null,
|
|
122
|
-
};
|
|
123
|
-
}
|
|
5
|
+
export default Platform.OS === 'web' ? useBackgroundWeb : useBackgroundNative;
|
|
@@ -156,7 +156,7 @@ const transforms = {
|
|
|
156
156
|
},
|
|
157
157
|
};
|
|
158
158
|
|
|
159
|
-
export default function
|
|
159
|
+
export default function useBackgroundNative(style: BaseStyle[]) {
|
|
160
160
|
const flattenedStyle = StyleSheet.flatten(style);
|
|
161
161
|
|
|
162
162
|
const background: BackgroundResult = {
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import type { BaseStyle } from '../types';
|
|
3
|
+
|
|
4
|
+
type Position = 'center' | 'left' | 'right' | 'top' | 'bottom';
|
|
5
|
+
type PositionX = 'center' | 'left' | 'right';
|
|
6
|
+
type PositionY = 'center' | 'top' | 'bottom';
|
|
7
|
+
|
|
8
|
+
type BackgroundWebStyle = BaseStyle & {
|
|
9
|
+
backgroundSize?:
|
|
10
|
+
| 'contain'
|
|
11
|
+
| 'cover'
|
|
12
|
+
| string
|
|
13
|
+
| number
|
|
14
|
+
| { width: 'auto' | number; height: 'auto' | number };
|
|
15
|
+
backgroundPosition?: Position;
|
|
16
|
+
backgroundPositionX?:
|
|
17
|
+
| PositionX
|
|
18
|
+
| { position: PositionX; offset: string | number };
|
|
19
|
+
backgroundPositionY?:
|
|
20
|
+
| PositionY
|
|
21
|
+
| { position: PositionY; offset: string | number };
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
type PositionValue = {
|
|
25
|
+
positionX: PositionX;
|
|
26
|
+
offsetX: string | number;
|
|
27
|
+
positionY: PositionY;
|
|
28
|
+
offsetY: string | number;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const styles = StyleSheet.create({
|
|
32
|
+
reset: {
|
|
33
|
+
// Background repeat is not supported on native yet.
|
|
34
|
+
// @ts-expect-error web only style
|
|
35
|
+
backgroundRepeat: 'no-repeat',
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const normalizeValue = (value: 'auto' | number | string) =>
|
|
40
|
+
typeof value === 'number' && value !== 0 ? `${value}px` : value;
|
|
41
|
+
|
|
42
|
+
const resolveBackgroundSize = (style: BackgroundWebStyle) => {
|
|
43
|
+
const { backgroundSize } = style;
|
|
44
|
+
|
|
45
|
+
if (typeof backgroundSize !== 'object') {
|
|
46
|
+
return backgroundSize;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const { width = 'auto', height = 'auto' } = backgroundSize;
|
|
50
|
+
|
|
51
|
+
return `${normalizeValue(width)} ${normalizeValue(height)}`;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const resolveBackgroundPosition = (style: BackgroundWebStyle) => {
|
|
55
|
+
const { backgroundPosition, backgroundPositionX, backgroundPositionY } =
|
|
56
|
+
style;
|
|
57
|
+
|
|
58
|
+
if (!backgroundPosition && !backgroundPositionX && !backgroundPositionY) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const value: PositionValue = {
|
|
63
|
+
positionX:
|
|
64
|
+
backgroundPosition === 'center' || backgroundPosition === 'right'
|
|
65
|
+
? backgroundPosition
|
|
66
|
+
: 'left',
|
|
67
|
+
offsetX: 0,
|
|
68
|
+
positionY:
|
|
69
|
+
backgroundPosition === 'center' || backgroundPosition === 'bottom'
|
|
70
|
+
? backgroundPosition
|
|
71
|
+
: 'top',
|
|
72
|
+
offsetY: 0,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
if (backgroundPositionX) {
|
|
76
|
+
const { position: positionX = 'left', offset: offsetX = 0 } =
|
|
77
|
+
typeof backgroundPositionX === 'object'
|
|
78
|
+
? backgroundPositionX
|
|
79
|
+
: { position: backgroundPositionX };
|
|
80
|
+
|
|
81
|
+
value.positionX = positionX;
|
|
82
|
+
value.offsetX = normalizeValue(offsetX);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (backgroundPositionY) {
|
|
86
|
+
const { position: positionY = 'top', offset: offsetY = 0 } =
|
|
87
|
+
typeof backgroundPositionY === 'object'
|
|
88
|
+
? backgroundPositionY
|
|
89
|
+
: { position: backgroundPositionY };
|
|
90
|
+
|
|
91
|
+
value.positionY = positionY;
|
|
92
|
+
value.offsetY = normalizeValue(offsetY);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const valueX = value.offsetX
|
|
96
|
+
? `${value.positionX} ${value.offsetX}`
|
|
97
|
+
: value.positionX;
|
|
98
|
+
const valueY = value.offsetY
|
|
99
|
+
? `${value.positionY} ${value.offsetY}`
|
|
100
|
+
: value.positionY;
|
|
101
|
+
|
|
102
|
+
return `${valueX} ${valueY}`;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export default function useBackgroundWeb(style: BaseStyle[]) {
|
|
106
|
+
const flattenedStyle = StyleSheet.flatten(style);
|
|
107
|
+
|
|
108
|
+
const backgroundStyle: BaseStyle = {
|
|
109
|
+
// Transform background size
|
|
110
|
+
// @ts-expect-error web only style
|
|
111
|
+
backgroundSize: resolveBackgroundSize(flattenedStyle),
|
|
112
|
+
// Workaround, because some browsers do not support two-value syntax:
|
|
113
|
+
// https://developer.mozilla.org/en-US/docs/Web/CSS/background-position-x#browser_compatibility
|
|
114
|
+
backgroundPositionX: null,
|
|
115
|
+
backgroundPositionY: null,
|
|
116
|
+
backgroundPosition: resolveBackgroundPosition(flattenedStyle),
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
style: [flattenedStyle, styles.reset, backgroundStyle],
|
|
121
|
+
element: null,
|
|
122
|
+
};
|
|
123
|
+
}
|