@react-navigation/elements 3.0.0-alpha.4 → 3.0.0-alpha.41
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/ActivityView.js +90 -0
- package/lib/module/ActivityView.js.map +1 -0
- package/lib/module/ActivityView.native.js +67 -0
- package/lib/module/ActivityView.native.js.map +1 -0
- package/lib/module/Badge.js +5 -4
- package/lib/module/Badge.js.map +1 -1
- package/lib/module/BlurEffectBackground.js +3 -3
- package/lib/module/BlurEffectBackground.js.map +1 -1
- package/lib/module/Button.js +96 -14
- package/lib/module/Button.js.map +1 -1
- package/lib/module/Color.js +565 -4
- package/lib/module/Color.js.map +1 -1
- package/lib/module/Container.js +11 -1
- package/lib/module/Container.js.map +1 -1
- package/lib/module/Header/Header.js +29 -17
- package/lib/module/Header/Header.js.map +1 -1
- package/lib/module/Header/HeaderBackButton.js +27 -13
- package/lib/module/Header/HeaderBackButton.js.map +1 -1
- package/lib/module/Header/HeaderButton.js +4 -5
- package/lib/module/Header/HeaderButton.js.map +1 -1
- package/lib/module/Header/HeaderButtonBackground.js +1 -2
- package/lib/module/Header/HeaderButtonBackground.js.map +1 -1
- package/lib/module/Header/HeaderIcon.js +14 -17
- package/lib/module/Header/HeaderIcon.js.map +1 -1
- package/lib/module/Header/HeaderSearchBar.js +35 -25
- package/lib/module/Header/HeaderSearchBar.js.map +1 -1
- package/lib/module/Header/getHeaderTitle.js.map +1 -1
- package/lib/module/Header/useHeaderHeight.js +1 -1
- package/lib/module/Header/useHeaderHeight.js.map +1 -1
- package/lib/module/Label/getLabel.js.map +1 -1
- package/lib/module/LiquidGlassView.ios.js +1 -2
- package/lib/module/LiquidGlassView.ios.js.map +1 -1
- package/lib/module/LiquidGlassView.js +0 -4
- package/lib/module/LiquidGlassView.js.map +1 -1
- package/lib/module/PlatformColor.js +1 -0
- package/lib/module/PlatformColor.js.map +1 -1
- package/lib/module/PlatformColor.native.js +1 -1
- package/lib/module/PlatformColor.native.js.map +1 -1
- package/lib/module/PlatformIcon.js +46 -0
- package/lib/module/PlatformIcon.js.map +1 -0
- package/lib/module/PlatformPressable.js +56 -14
- package/lib/module/PlatformPressable.js.map +1 -1
- package/lib/module/SafeAreaProviderCompat.js +1 -1
- package/lib/module/SafeAreaProviderCompat.js.map +1 -1
- package/lib/module/Screen.js +31 -18
- package/lib/module/Screen.js.map +1 -1
- package/lib/module/index.js +2 -7
- package/lib/module/index.js.map +1 -1
- package/lib/module/internal.js +1 -1
- package/lib/module/internal.js.map +1 -1
- package/lib/module/useFrameSize.js +6 -2
- package/lib/module/useFrameSize.js.map +1 -1
- package/lib/typescript/src/ActivityView.d.ts +31 -0
- package/lib/typescript/src/ActivityView.d.ts.map +1 -0
- package/lib/typescript/src/ActivityView.native.d.ts +3 -0
- package/lib/typescript/src/ActivityView.native.d.ts.map +1 -0
- package/lib/typescript/src/Badge.d.ts +6 -5
- package/lib/typescript/src/Badge.d.ts.map +1 -1
- package/lib/typescript/src/BlurEffectBackground.d.ts +2 -2
- package/lib/typescript/src/BlurEffectBackground.d.ts.map +1 -1
- package/lib/typescript/src/Button.d.ts +54 -6
- package/lib/typescript/src/Button.d.ts.map +1 -1
- package/lib/typescript/src/Color.d.ts +4 -4
- package/lib/typescript/src/Color.d.ts.map +1 -1
- package/lib/typescript/src/Container.d.ts +7 -4
- package/lib/typescript/src/Container.d.ts.map +1 -1
- package/lib/typescript/src/Header/Header.d.ts +5 -4
- package/lib/typescript/src/Header/Header.d.ts.map +1 -1
- package/lib/typescript/src/Header/HeaderBackButton.d.ts +3 -2
- package/lib/typescript/src/Header/HeaderBackButton.d.ts.map +1 -1
- package/lib/typescript/src/Header/HeaderBackground.d.ts +5 -5
- package/lib/typescript/src/Header/HeaderBackground.d.ts.map +1 -1
- package/lib/typescript/src/Header/HeaderButton.d.ts +7 -2
- package/lib/typescript/src/Header/HeaderButton.d.ts.map +1 -1
- package/lib/typescript/src/Header/HeaderButtonBackground.d.ts +1 -1
- package/lib/typescript/src/Header/HeaderButtonBackground.d.ts.map +1 -1
- package/lib/typescript/src/Header/HeaderIcon.d.ts +9 -4
- package/lib/typescript/src/Header/HeaderIcon.d.ts.map +1 -1
- package/lib/typescript/src/Header/HeaderSearchBar.d.ts +10 -7
- package/lib/typescript/src/Header/HeaderSearchBar.d.ts.map +1 -1
- package/lib/typescript/src/Header/HeaderTitle.d.ts +4 -4
- package/lib/typescript/src/Header/HeaderTitle.d.ts.map +1 -1
- package/lib/typescript/src/Header/getHeaderTitle.d.ts +2 -2
- package/lib/typescript/src/Header/getHeaderTitle.d.ts.map +1 -1
- package/lib/typescript/src/Label/Label.d.ts +1 -1
- package/lib/typescript/src/Label/Label.d.ts.map +1 -1
- package/lib/typescript/src/Label/getLabel.d.ts +2 -2
- package/lib/typescript/src/Label/getLabel.d.ts.map +1 -1
- package/lib/typescript/src/LiquidGlassView.d.ts +7 -5
- package/lib/typescript/src/LiquidGlassView.d.ts.map +1 -1
- package/lib/typescript/src/LiquidGlassView.ios.d.ts +4 -2
- package/lib/typescript/src/LiquidGlassView.ios.d.ts.map +1 -1
- package/lib/typescript/src/MissingIcon.d.ts +1 -1
- package/lib/typescript/src/MissingIcon.d.ts.map +1 -1
- package/lib/typescript/src/PlatformColor.d.ts +1 -0
- package/lib/typescript/src/PlatformColor.d.ts.map +1 -1
- package/lib/typescript/src/PlatformColor.native.d.ts +1 -1
- package/lib/typescript/src/PlatformColor.native.d.ts.map +1 -1
- package/lib/typescript/src/PlatformIcon.d.ts +10 -0
- package/lib/typescript/src/PlatformIcon.d.ts.map +1 -0
- package/lib/typescript/src/PlatformPressable.d.ts +12 -15
- package/lib/typescript/src/PlatformPressable.d.ts.map +1 -1
- package/lib/typescript/src/SafeAreaProviderCompat.d.ts +1 -1
- package/lib/typescript/src/SafeAreaProviderCompat.d.ts.map +1 -1
- package/lib/typescript/src/Screen.d.ts +7 -7
- package/lib/typescript/src/Screen.d.ts.map +1 -1
- package/lib/typescript/src/Text.d.ts +1 -1
- package/lib/typescript/src/Text.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +21 -21
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/internal.d.ts +6 -6
- package/lib/typescript/src/internal.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +120 -70
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/useFrameSize.d.ts +1 -1
- package/lib/typescript/src/useFrameSize.d.ts.map +1 -1
- package/package.json +23 -22
- package/src/ActivityView.native.tsx +90 -0
- package/src/ActivityView.tsx +129 -0
- package/src/Badge.tsx +10 -8
- package/src/BlurEffectBackground.tsx +3 -3
- package/src/Button.tsx +173 -28
- package/src/Color.tsx +755 -8
- package/src/Container.tsx +20 -4
- package/src/Header/Header.tsx +46 -26
- package/src/Header/HeaderBackButton.tsx +31 -17
- package/src/Header/HeaderBackground.tsx +3 -3
- package/src/Header/HeaderButton.tsx +16 -18
- package/src/Header/HeaderButtonBackground.tsx +1 -4
- package/src/Header/HeaderIcon.tsx +27 -13
- package/src/Header/HeaderSearchBar.tsx +52 -44
- package/src/Header/HeaderTitle.tsx +3 -3
- package/src/Header/getHeaderTitle.tsx +4 -1
- package/src/Header/useHeaderHeight.tsx +1 -1
- package/src/Label/getLabel.tsx +1 -1
- package/src/LiquidGlassView.ios.tsx +14 -9
- package/src/LiquidGlassView.tsx +15 -11
- package/src/PlatformColor.native.tsx +1 -1
- package/src/PlatformColor.tsx +4 -0
- package/src/PlatformIcon.tsx +66 -0
- package/src/PlatformPressable.tsx +99 -41
- package/src/SafeAreaProviderCompat.tsx +1 -1
- package/src/Screen.tsx +40 -27
- package/src/index.tsx +2 -16
- package/src/internal.tsx +1 -1
- package/src/types.tsx +153 -76
- package/src/useFrameSize.tsx +9 -2
- package/lib/module/Lazy.js +0 -42
- package/lib/module/Lazy.js.map +0 -1
- package/lib/module/assets/back-icon.ios.svg +0 -4
- package/lib/module/assets/back-icon@1x.android.png +0 -0
- package/lib/module/assets/back-icon@1x.ios.png +0 -0
- package/lib/module/assets/back-icon@2x.android.png +0 -0
- package/lib/module/assets/back-icon@2x.ios.png +0 -0
- package/lib/module/assets/back-icon@3x.android.png +0 -0
- package/lib/module/assets/back-icon@3x.ios.png +0 -0
- package/lib/module/assets/back-icon@4x.android.png +0 -0
- package/lib/module/assets/back-icon@4x.ios.png +0 -0
- package/lib/module/assets/clear-icon@1x.png +0 -0
- package/lib/module/assets/clear-icon@2x.png +0 -0
- package/lib/module/assets/clear-icon@3x.png +0 -0
- package/lib/module/assets/clear-icon@4x.png +0 -0
- package/lib/module/assets/close-icon@1x.png +0 -0
- package/lib/module/assets/close-icon@2x.png +0 -0
- package/lib/module/assets/close-icon@3x.png +0 -0
- package/lib/module/assets/close-icon@4x.png +0 -0
- package/lib/module/assets/search-icon-legacy@1x.ios.png +0 -0
- package/lib/module/assets/search-icon-legacy@2x.ios.png +0 -0
- package/lib/module/assets/search-icon-legacy@3x.ios.png +0 -0
- package/lib/module/assets/search-icon-legacy@4x.ios.png +0 -0
- package/lib/module/assets/search-icon.ios.svg +0 -4
- package/lib/module/assets/search-icon@1x.android.png +0 -0
- package/lib/module/assets/search-icon@1x.ios.png +0 -0
- package/lib/module/assets/search-icon@2x.android.png +0 -0
- package/lib/module/assets/search-icon@2x.ios.png +0 -0
- package/lib/module/assets/search-icon@3x.android.png +0 -0
- package/lib/module/assets/search-icon@3x.ios.png +0 -0
- package/lib/module/assets/search-icon@4x.android.png +0 -0
- package/lib/module/assets/search-icon@4x.ios.png +0 -0
- package/lib/typescript/src/Lazy.d.ts +0 -31
- package/lib/typescript/src/Lazy.d.ts.map +0 -1
- package/src/Lazy.tsx +0 -59
- package/src/assets/back-icon.ios.svg +0 -4
- package/src/assets/back-icon@1x.android.png +0 -0
- package/src/assets/back-icon@1x.ios.png +0 -0
- package/src/assets/back-icon@2x.android.png +0 -0
- package/src/assets/back-icon@2x.ios.png +0 -0
- package/src/assets/back-icon@3x.android.png +0 -0
- package/src/assets/back-icon@3x.ios.png +0 -0
- package/src/assets/back-icon@4x.android.png +0 -0
- package/src/assets/back-icon@4x.ios.png +0 -0
- package/src/assets/clear-icon@1x.png +0 -0
- package/src/assets/clear-icon@2x.png +0 -0
- package/src/assets/clear-icon@3x.png +0 -0
- package/src/assets/clear-icon@4x.png +0 -0
- package/src/assets/close-icon@1x.png +0 -0
- package/src/assets/close-icon@2x.png +0 -0
- package/src/assets/close-icon@3x.png +0 -0
- package/src/assets/close-icon@4x.png +0 -0
- package/src/assets/search-icon-legacy@1x.ios.png +0 -0
- package/src/assets/search-icon-legacy@2x.ios.png +0 -0
- package/src/assets/search-icon-legacy@3x.ios.png +0 -0
- package/src/assets/search-icon-legacy@4x.ios.png +0 -0
- package/src/assets/search-icon.ios.svg +0 -4
- package/src/assets/search-icon@1x.android.png +0 -0
- package/src/assets/search-icon@1x.ios.png +0 -0
- package/src/assets/search-icon@2x.android.png +0 -0
- package/src/assets/search-icon@2x.ios.png +0 -0
- package/src/assets/search-icon@3x.android.png +0 -0
- package/src/assets/search-icon@3x.ios.png +0 -0
- package/src/assets/search-icon@4x.android.png +0 -0
- package/src/assets/search-icon@4x.ios.png +0 -0
|
@@ -12,6 +12,6 @@ type FrameSizeProviderProps = {
|
|
|
12
12
|
onLayout: (event: LayoutChangeEvent) => void;
|
|
13
13
|
}) => React.ReactNode;
|
|
14
14
|
};
|
|
15
|
-
export declare function FrameSizeProvider({ initialFrame, render, }: FrameSizeProviderProps):
|
|
15
|
+
export declare function FrameSizeProvider({ initialFrame, render, }: FrameSizeProviderProps): React.JSX.Element;
|
|
16
16
|
export {};
|
|
17
17
|
//# sourceMappingURL=useFrameSize.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFrameSize.d.ts","sourceRoot":"","sources":["../../../src/useFrameSize.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,KAAK,iBAAiB,EAAY,IAAI,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"useFrameSize.d.ts","sourceRoot":"","sources":["../../../src/useFrameSize.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,KAAK,iBAAiB,EAAY,IAAI,EAAE,MAAM,cAAc,CAAC;AAMtE,KAAK,KAAK,GAAG;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAiBF,wBAAgB,YAAY,CAAC,CAAC,EAC5B,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,CAAC,EAC7B,QAAQ,CAAC,EAAE,OAAO,GACjB,CAAC,CAeH;AAED,KAAK,sBAAsB,GAAG;IAC5B,YAAY,EAAE,KAAK,CAAC;IACpB,MAAM,EAAE,CAAC,KAAK,EAAE;QACd,GAAG,EAAE,KAAK,CAAC,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QAClC,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;KAC9C,KAAK,KAAK,CAAC,SAAS,CAAC;CACvB,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,EAChC,YAAY,EACZ,MAAM,GACP,EAAE,sBAAsB,qBA4GxB"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-navigation/elements",
|
|
3
3
|
"description": "UI Components for React Navigation",
|
|
4
|
-
"version": "3.0.0-alpha.
|
|
4
|
+
"version": "3.0.0-alpha.41",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
7
7
|
"react-navigation",
|
|
@@ -22,12 +22,12 @@
|
|
|
22
22
|
"types": "./lib/typescript/src/index.d.ts",
|
|
23
23
|
"exports": {
|
|
24
24
|
".": {
|
|
25
|
-
"source": "./src/index.tsx",
|
|
25
|
+
"@react-navigation/source": "./src/index.tsx",
|
|
26
26
|
"types": "./lib/typescript/src/index.d.ts",
|
|
27
27
|
"default": "./lib/module/index.js"
|
|
28
28
|
},
|
|
29
29
|
"./internal": {
|
|
30
|
-
"source": "./src/internal.tsx",
|
|
30
|
+
"@react-navigation/source": "./src/internal.tsx",
|
|
31
31
|
"types": "./lib/typescript/src/internal.d.ts",
|
|
32
32
|
"default": "./lib/module/internal.js"
|
|
33
33
|
},
|
|
@@ -47,32 +47,33 @@
|
|
|
47
47
|
"clean": "del lib"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"
|
|
51
|
-
"use-latest-callback": "^0.3.
|
|
52
|
-
"use-sync-external-store": "^1.
|
|
50
|
+
"sf-symbols-typescript": "^2.2.0",
|
|
51
|
+
"use-latest-callback": "^0.3.4",
|
|
52
|
+
"use-sync-external-store": "^1.6.0"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"@callstack/liquid-glass": "^0.
|
|
56
|
-
"@jest/globals": "^
|
|
57
|
-
"@react-navigation/native": "^8.0.0-alpha.
|
|
58
|
-
"@testing-library/react-native": "^
|
|
59
|
-
"@types/react": "~19.
|
|
55
|
+
"@callstack/liquid-glass": "^0.8.0",
|
|
56
|
+
"@jest/globals": "^29.7.0",
|
|
57
|
+
"@react-navigation/native": "^8.0.0-alpha.37",
|
|
58
|
+
"@testing-library/react-native": "^14.0.0",
|
|
59
|
+
"@types/react": "~19.2.17",
|
|
60
60
|
"@types/use-sync-external-store": "^1.5.0",
|
|
61
|
-
"del-cli": "^
|
|
62
|
-
"react": "19.
|
|
63
|
-
"react-native": "0.
|
|
64
|
-
"react-native-builder-bob": "^0.
|
|
65
|
-
"react-native-
|
|
66
|
-
"react-
|
|
67
|
-
"
|
|
61
|
+
"del-cli": "^7.0.0",
|
|
62
|
+
"react": "19.2.3",
|
|
63
|
+
"react-native": "0.85.3",
|
|
64
|
+
"react-native-builder-bob": "^0.43.0",
|
|
65
|
+
"react-native-safe-area-context": "~5.7.0",
|
|
66
|
+
"react-native-screens": "^4.26.2",
|
|
67
|
+
"test-renderer": "1.2.0",
|
|
68
|
+
"typescript": "^6.0.3"
|
|
68
69
|
},
|
|
69
70
|
"peerDependencies": {
|
|
70
71
|
"@callstack/liquid-glass": ">= 0.6.0",
|
|
71
|
-
"@react-navigation/native": "^8.0.0-alpha.
|
|
72
|
-
"react": ">= 19.
|
|
72
|
+
"@react-navigation/native": "^8.0.0-alpha.37",
|
|
73
|
+
"react": ">= 19.2.0",
|
|
73
74
|
"react-native": "*",
|
|
74
75
|
"react-native-safe-area-context": ">= 5.5.0",
|
|
75
|
-
"react-native-screens": ">= 4.
|
|
76
|
+
"react-native-screens": ">= 4.25.0"
|
|
76
77
|
},
|
|
77
78
|
"react-native-builder-bob": {
|
|
78
79
|
"source": "src",
|
|
@@ -92,5 +93,5 @@
|
|
|
92
93
|
]
|
|
93
94
|
]
|
|
94
95
|
},
|
|
95
|
-
"gitHead": "
|
|
96
|
+
"gitHead": "b0135879fbe4aa4a657798845483b7e78c307778"
|
|
96
97
|
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Activity, useEffect, useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
type HostComponent,
|
|
4
|
+
NativeComponentRegistry,
|
|
5
|
+
type ViewProps,
|
|
6
|
+
} from 'react-native';
|
|
7
|
+
|
|
8
|
+
// eslint-disable-next-line import-x/extensions
|
|
9
|
+
import type { Props } from './ActivityView.tsx';
|
|
10
|
+
import { Container } from './Container';
|
|
11
|
+
|
|
12
|
+
export function ActivityView({
|
|
13
|
+
mode,
|
|
14
|
+
visible,
|
|
15
|
+
delay = 500,
|
|
16
|
+
style,
|
|
17
|
+
children,
|
|
18
|
+
}: Props) {
|
|
19
|
+
const [delayedMode, setDelayedMode] = useState(mode);
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (!delay) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const timer = setTimeout(() => {
|
|
27
|
+
setDelayedMode(mode);
|
|
28
|
+
}, delay);
|
|
29
|
+
|
|
30
|
+
return () => clearTimeout(timer);
|
|
31
|
+
}, [delay, mode]);
|
|
32
|
+
|
|
33
|
+
const display = visible ? 'flex' : 'none';
|
|
34
|
+
const activityMode =
|
|
35
|
+
mode !== 'paused' || (delay && delayedMode !== 'paused')
|
|
36
|
+
? 'visible'
|
|
37
|
+
: 'hidden';
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<Activity mode={activityMode}>
|
|
41
|
+
<ActivityContentView style={{ display: 'contents' }}>
|
|
42
|
+
<Container
|
|
43
|
+
inert={mode !== 'normal'}
|
|
44
|
+
style={{
|
|
45
|
+
...style,
|
|
46
|
+
/**
|
|
47
|
+
* The visibility of the nested view is controlled by `Activity`
|
|
48
|
+
* It'll be overridden to `display: 'none'` when `mode="hidden"` regardless of what we set
|
|
49
|
+
* So we set the visibility on another view instead
|
|
50
|
+
*/
|
|
51
|
+
display,
|
|
52
|
+
}}
|
|
53
|
+
>
|
|
54
|
+
{children}
|
|
55
|
+
</Container>
|
|
56
|
+
</ActivityContentView>
|
|
57
|
+
</Activity>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const STYLE: Record<string, true | { process?: (arg1: any) => any }> = {
|
|
62
|
+
display: {
|
|
63
|
+
/**
|
|
64
|
+
* React `Activity` sets `display: 'none'` when `mode="hidden"` to unmount effects
|
|
65
|
+
* But we want to keep the content visible, so we switch it to `display: 'contents'`
|
|
66
|
+
*/
|
|
67
|
+
process: () => 'contents',
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const VIEW_CONFIG = {
|
|
72
|
+
uiViewClassName: 'RCTView',
|
|
73
|
+
validAttributes: {
|
|
74
|
+
style: STYLE,
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
type ActivityContentViewProps = Omit<ViewProps, 'style'> & {
|
|
79
|
+
style?:
|
|
80
|
+
| {
|
|
81
|
+
display?: 'contents' | undefined;
|
|
82
|
+
}
|
|
83
|
+
| undefined;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const ActivityContentView: HostComponent<ActivityContentViewProps> =
|
|
87
|
+
NativeComponentRegistry.get<ActivityContentViewProps>(
|
|
88
|
+
'ReactNavigationActivityContentView',
|
|
89
|
+
() => VIEW_CONFIG
|
|
90
|
+
);
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { Activity, useCallback, useEffect, useState } from 'react';
|
|
2
|
+
import { Platform, View, type ViewStyle } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { Container } from './Container';
|
|
5
|
+
|
|
6
|
+
export type Props = {
|
|
7
|
+
/**
|
|
8
|
+
* Mode of the activity view
|
|
9
|
+
* - `normal`: The view renders normally
|
|
10
|
+
* - `inert`: Content is not interactive
|
|
11
|
+
* - `paused`: Effects are unmounted and content is not interactive
|
|
12
|
+
*/
|
|
13
|
+
mode: 'normal' | 'inert' | 'paused';
|
|
14
|
+
/**
|
|
15
|
+
* Whether the content is visible or not
|
|
16
|
+
*/
|
|
17
|
+
visible: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Delay before pausing effects.
|
|
20
|
+
* So pending animations have time to finish.
|
|
21
|
+
*
|
|
22
|
+
* Defaults to 500ms.
|
|
23
|
+
*/
|
|
24
|
+
delay?: number | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* The style for the container view
|
|
27
|
+
*/
|
|
28
|
+
style?: Omit<React.CSSProperties & ViewStyle, 'display'> | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* The content of the activity view
|
|
31
|
+
*/
|
|
32
|
+
children: React.ReactNode;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export function ActivityView({
|
|
36
|
+
mode,
|
|
37
|
+
visible,
|
|
38
|
+
delay = 500,
|
|
39
|
+
style,
|
|
40
|
+
children,
|
|
41
|
+
}: Props) {
|
|
42
|
+
const [delayedMode, setDelayedMode] = useState(mode);
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (!delay) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const timer = setTimeout(() => {
|
|
50
|
+
setDelayedMode(mode);
|
|
51
|
+
}, delay);
|
|
52
|
+
|
|
53
|
+
return () => clearTimeout(timer);
|
|
54
|
+
}, [delay, mode]);
|
|
55
|
+
|
|
56
|
+
const display = visible ? 'flex' : 'none';
|
|
57
|
+
const activityMode =
|
|
58
|
+
mode !== 'paused' || (delay && delayedMode !== 'paused')
|
|
59
|
+
? 'visible'
|
|
60
|
+
: 'hidden';
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Activity has 2 modes, visible and hidden - hidden unmounts effects
|
|
64
|
+
* But what we want is to unmount effects, without hiding content
|
|
65
|
+
* So we use hidden mode, but unset display: none to make content visible
|
|
66
|
+
*/
|
|
67
|
+
const onRef = useCallback(
|
|
68
|
+
(node: HTMLDivElement | View | null) => {
|
|
69
|
+
if (Platform.OS !== 'web' || !(node && node instanceof HTMLElement)) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const observers: MutationObserver[] = [];
|
|
74
|
+
|
|
75
|
+
const observe = () => {
|
|
76
|
+
// Remove previous observers
|
|
77
|
+
observers.forEach((o) => o.disconnect());
|
|
78
|
+
observers.length = 0;
|
|
79
|
+
|
|
80
|
+
const children = node.childNodes;
|
|
81
|
+
|
|
82
|
+
// When the style attribute for children is updated by React
|
|
83
|
+
// We observe it and update display to make content visible
|
|
84
|
+
children.forEach((child) => {
|
|
85
|
+
if (child instanceof HTMLElement) {
|
|
86
|
+
child.style.display = display;
|
|
87
|
+
|
|
88
|
+
const o = new MutationObserver(() => {
|
|
89
|
+
child.style.display = display;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
o.observe(child, {
|
|
93
|
+
attributes: true,
|
|
94
|
+
attributeFilter: ['style'],
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
observers.push(o);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
observe();
|
|
103
|
+
|
|
104
|
+
// React removes refs when `Activity` is hidden
|
|
105
|
+
// So we render outside of the `Activity` and observer child list
|
|
106
|
+
const observer = new MutationObserver(observe);
|
|
107
|
+
|
|
108
|
+
observer.observe(node, {
|
|
109
|
+
childList: true,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
return () => {
|
|
113
|
+
observer.disconnect();
|
|
114
|
+
observers.forEach((o) => o.disconnect());
|
|
115
|
+
};
|
|
116
|
+
},
|
|
117
|
+
[display]
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<Container ref={onRef} style={{ display: 'contents' }}>
|
|
122
|
+
<Activity mode={activityMode}>
|
|
123
|
+
<Container inert={mode !== 'normal'} style={{ ...style, display }}>
|
|
124
|
+
{children}
|
|
125
|
+
</Container>
|
|
126
|
+
</Activity>
|
|
127
|
+
</Container>
|
|
128
|
+
);
|
|
129
|
+
}
|
package/src/Badge.tsx
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
|
|
12
12
|
import { Color } from './Color';
|
|
13
13
|
|
|
14
|
-
type Props = TextProps & {
|
|
14
|
+
type Props = Omit<TextProps, 'style'> & {
|
|
15
15
|
/**
|
|
16
16
|
* Whether the badge is visible
|
|
17
17
|
*/
|
|
@@ -19,15 +19,15 @@ type Props = TextProps & {
|
|
|
19
19
|
/**
|
|
20
20
|
* Content of the `Badge`.
|
|
21
21
|
*/
|
|
22
|
-
children?: string | number;
|
|
22
|
+
children?: string | number | undefined;
|
|
23
23
|
/**
|
|
24
24
|
* Size of the `Badge`.
|
|
25
25
|
*/
|
|
26
|
-
size?: number;
|
|
26
|
+
size?: number | undefined;
|
|
27
27
|
/**
|
|
28
28
|
* Style object for the tab bar container.
|
|
29
29
|
*/
|
|
30
|
-
style?: Animated.WithAnimatedValue<StyleProp<TextStyle
|
|
30
|
+
style?: Animated.WithAnimatedValue<StyleProp<TextStyle>> | undefined;
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
const useNativeDriver = Platform.OS !== 'web';
|
|
@@ -49,17 +49,19 @@ export function Badge({
|
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
Animated.timing(opacity, {
|
|
52
|
+
const animation = Animated.timing(opacity, {
|
|
53
53
|
toValue: visible ? 1 : 0,
|
|
54
54
|
duration: 150,
|
|
55
55
|
useNativeDriver,
|
|
56
|
-
})
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
animation.start(({ finished }) => {
|
|
57
59
|
if (finished && !visible) {
|
|
58
60
|
setRendered(false);
|
|
59
61
|
}
|
|
60
62
|
});
|
|
61
63
|
|
|
62
|
-
return () =>
|
|
64
|
+
return () => animation.stop();
|
|
63
65
|
}, [opacity, rendered, visible]);
|
|
64
66
|
|
|
65
67
|
if (!rendered) {
|
|
@@ -73,7 +75,7 @@ export function Badge({
|
|
|
73
75
|
// @ts-expect-error: backgroundColor definitely exists
|
|
74
76
|
const { backgroundColor = colors.notification, ...restStyle } =
|
|
75
77
|
StyleSheet.flatten(style) || {};
|
|
76
|
-
const textColor = Color(backgroundColor)
|
|
78
|
+
const textColor = Color.foreground(backgroundColor);
|
|
77
79
|
|
|
78
80
|
const borderRadius = size / 2;
|
|
79
81
|
const fontSize = Math.floor((size * 3) / 4);
|
|
@@ -31,7 +31,8 @@ export function BlurEffectBackground({
|
|
|
31
31
|
children,
|
|
32
32
|
...rest
|
|
33
33
|
}: Props) {
|
|
34
|
-
let
|
|
34
|
+
let blurStyle: (ViewStyle & React.CSSProperties) | undefined;
|
|
35
|
+
let containerStyle, blurBackground, colorBackground;
|
|
35
36
|
|
|
36
37
|
if (Platform.OS === 'web' && blurEffect && blurEffect !== 'none') {
|
|
37
38
|
const blurBackgroundColor = getBlurBackgroundColor(blurEffect);
|
|
@@ -40,9 +41,8 @@ export function BlurEffectBackground({
|
|
|
40
41
|
const backdropFilter = `saturate(180%) blur(30px)`;
|
|
41
42
|
|
|
42
43
|
blurStyle = {
|
|
43
|
-
// @ts-expect-error backdropFilter is web-only
|
|
44
44
|
backdropFilter,
|
|
45
|
-
|
|
45
|
+
WebkitBackdropFilter: backdropFilter,
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
blurBackground = (
|
package/src/Button.tsx
CHANGED
|
@@ -1,71 +1,156 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type LinkProps,
|
|
3
|
+
type ParamListBase,
|
|
3
4
|
type RootParamList,
|
|
4
5
|
useLinkProps,
|
|
5
6
|
useTheme,
|
|
6
7
|
} from '@react-navigation/native';
|
|
7
8
|
import * as React from 'react';
|
|
8
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
ActivityIndicator,
|
|
11
|
+
type ColorValue,
|
|
12
|
+
Platform,
|
|
13
|
+
StyleSheet,
|
|
14
|
+
View,
|
|
15
|
+
} from 'react-native';
|
|
9
16
|
|
|
10
17
|
import { Color } from './Color';
|
|
18
|
+
import { PlatformIcon } from './PlatformIcon';
|
|
11
19
|
import {
|
|
12
20
|
PlatformPressable,
|
|
13
21
|
type Props as PlatformPressableProps,
|
|
14
22
|
} from './PlatformPressable';
|
|
15
23
|
import { Text } from './Text';
|
|
24
|
+
import type { Icon } from './types';
|
|
16
25
|
|
|
17
26
|
type ButtonBaseProps = Omit<PlatformPressableProps, 'children'> & {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Variant of the button.
|
|
29
|
+
*
|
|
30
|
+
* - `plain`: transparent background, colored text
|
|
31
|
+
* - `tinted`: lightly tinted background, colored text
|
|
32
|
+
* - `filled`: colored background, contrasting text color
|
|
33
|
+
*
|
|
34
|
+
* @default 'tinted'
|
|
35
|
+
*/
|
|
36
|
+
variant?: 'plain' | 'tinted' | 'filled' | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Custom color for the button.
|
|
39
|
+
* Changes the text color for `plain` and `tinted` variants,
|
|
40
|
+
* and background color for `filled` variant.
|
|
41
|
+
*/
|
|
42
|
+
color?: ColorValue | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Icon to display before the label.
|
|
45
|
+
*
|
|
46
|
+
* Supported types:
|
|
47
|
+
* - image: custom image source
|
|
48
|
+
* - sfSymbol: SF Symbol icon (iOS only)
|
|
49
|
+
* - materialSymbol: material symbol icon (Android only)
|
|
50
|
+
* - React Node: function that returns a React Element
|
|
51
|
+
*/
|
|
52
|
+
icon?:
|
|
53
|
+
| Icon
|
|
54
|
+
| ((props: { color: ColorValue; size: number }) => Icon | React.ReactNode)
|
|
55
|
+
| undefined;
|
|
56
|
+
/**
|
|
57
|
+
* Whether to show a loading indicator instead of the icon.
|
|
58
|
+
*/
|
|
59
|
+
loading?: boolean | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* Label text to display inside the button.
|
|
62
|
+
*/
|
|
63
|
+
children: string | string[] | React.ReactElement | React.ReactElement[];
|
|
21
64
|
};
|
|
22
65
|
|
|
23
66
|
type ButtonLinkProps<
|
|
24
67
|
ParamList extends {} = RootParamList,
|
|
25
|
-
RouteName extends keyof ParamList =
|
|
26
|
-
|
|
68
|
+
RouteName extends Extract<keyof ParamList, string> = Extract<
|
|
69
|
+
keyof ParamList,
|
|
70
|
+
string
|
|
71
|
+
>,
|
|
72
|
+
> = LinkProps<NoInfer<ParamList>, RouteName> & ButtonBaseProps;
|
|
27
73
|
|
|
28
74
|
const BUTTON_RADIUS = 40;
|
|
75
|
+
const ICON_SIZE = 14;
|
|
29
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Component to render a button that navigates to a screen using a path.
|
|
79
|
+
* Uses an anchor tag on the web.
|
|
80
|
+
*
|
|
81
|
+
* @param props.in Name of the current or parent screen whose navigator contains the target screen.
|
|
82
|
+
* @param props.screen Name of the screen to navigate to (e.g. `'Feeds'`).
|
|
83
|
+
* @param props.params Params to pass to the screen to navigate to (e.g. `{ sort: 'hot' }`).
|
|
84
|
+
* @param props.href Optional absolute path to use for the href (e.g. `/feeds/hot`).
|
|
85
|
+
* @param props.action Optional action to override the in-page navigation. The `href` is still derived from `screen`, so this can be used to render a link while dispatching a different action (e.g. a `replace`).
|
|
86
|
+
*/
|
|
30
87
|
export function Button<
|
|
31
88
|
ParamList extends {} = RootParamList,
|
|
32
|
-
RouteName extends keyof ParamList =
|
|
89
|
+
RouteName extends Extract<keyof ParamList, string> = Extract<
|
|
90
|
+
keyof ParamList,
|
|
91
|
+
string
|
|
92
|
+
>,
|
|
33
93
|
>(props: ButtonLinkProps<ParamList, RouteName>): React.JSX.Element;
|
|
34
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Component to render a button.
|
|
97
|
+
*/
|
|
35
98
|
export function Button(props: ButtonBaseProps): React.JSX.Element;
|
|
36
99
|
|
|
37
|
-
export function Button
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
>(props: ButtonBaseProps | ButtonLinkProps<ParamList, RouteName>) {
|
|
100
|
+
export function Button(
|
|
101
|
+
props: ButtonBaseProps | ButtonLinkProps<ParamListBase>
|
|
102
|
+
) {
|
|
41
103
|
if ('screen' in props || 'action' in props) {
|
|
42
|
-
// @ts-expect-error: This is already type-checked by the prop types
|
|
43
104
|
return <ButtonLink {...props} />;
|
|
44
105
|
} else {
|
|
45
106
|
return <ButtonBase {...props} />;
|
|
46
107
|
}
|
|
47
108
|
}
|
|
48
109
|
|
|
49
|
-
function ButtonLink
|
|
50
|
-
|
|
51
|
-
const RouteName extends keyof ParamList = keyof ParamList,
|
|
52
|
-
>({
|
|
110
|
+
function ButtonLink({
|
|
111
|
+
in: parent,
|
|
53
112
|
screen,
|
|
54
113
|
params,
|
|
55
114
|
action,
|
|
56
115
|
href,
|
|
116
|
+
onPress,
|
|
57
117
|
...rest
|
|
58
|
-
}: ButtonLinkProps<
|
|
59
|
-
// @ts-expect-error:
|
|
60
|
-
const props = useLinkProps({ screen, params, action, href });
|
|
118
|
+
}: ButtonLinkProps<ParamListBase>) {
|
|
119
|
+
// @ts-expect-error: destructuring loses the relationship between target props
|
|
120
|
+
const props = useLinkProps({ in: parent, screen, params, action, href });
|
|
121
|
+
|
|
122
|
+
const [isPending, startTransition] = React.useTransition();
|
|
123
|
+
|
|
124
|
+
// Avoid flashing the loading indicator when the transition is fast
|
|
125
|
+
const isPendingDeferred = React.useDeferredValue(isPending);
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<ButtonBase
|
|
129
|
+
{...rest}
|
|
130
|
+
{...props}
|
|
131
|
+
loading={
|
|
132
|
+
typeof rest.loading === 'boolean'
|
|
133
|
+
? rest.loading
|
|
134
|
+
: isPending && isPendingDeferred
|
|
135
|
+
}
|
|
136
|
+
onPress={(e) => {
|
|
137
|
+
onPress?.(e);
|
|
61
138
|
|
|
62
|
-
|
|
139
|
+
startTransition(() => {
|
|
140
|
+
props.onPress(e);
|
|
141
|
+
});
|
|
142
|
+
}}
|
|
143
|
+
/>
|
|
144
|
+
);
|
|
63
145
|
}
|
|
64
146
|
|
|
65
147
|
function ButtonBase({
|
|
66
148
|
variant = 'tinted',
|
|
67
149
|
color: customColor,
|
|
150
|
+
icon,
|
|
151
|
+
loading = false,
|
|
68
152
|
android_ripple,
|
|
153
|
+
disabled,
|
|
69
154
|
style,
|
|
70
155
|
children,
|
|
71
156
|
...rest
|
|
@@ -90,18 +175,39 @@ function ButtonBase({
|
|
|
90
175
|
break;
|
|
91
176
|
case 'filled':
|
|
92
177
|
backgroundColor = color;
|
|
93
|
-
textColor = Color(
|
|
94
|
-
? 'white'
|
|
95
|
-
: (Color(color)?.darken(0.71).string() ?? '#fff');
|
|
178
|
+
textColor = Color.foreground(backgroundColor);
|
|
96
179
|
break;
|
|
97
180
|
}
|
|
98
181
|
|
|
182
|
+
if (disabled || loading) {
|
|
183
|
+
textColor = dark ? 'rgba(235, 235, 245, 0.3)' : 'rgba(60, 60, 67, 0.3)';
|
|
184
|
+
|
|
185
|
+
if (variant !== 'plain') {
|
|
186
|
+
backgroundColor = dark
|
|
187
|
+
? 'rgba(118, 118, 128, 0.24)'
|
|
188
|
+
: 'rgba(118, 118, 128, 0.12)';
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const rippleColor =
|
|
193
|
+
Color(textColor)?.fade(0.88).string() ??
|
|
194
|
+
(variant === 'filled' || dark
|
|
195
|
+
? 'rgba(255, 255, 255, 0.12)'
|
|
196
|
+
: 'rgba(0, 0, 0, 0.12)');
|
|
197
|
+
|
|
198
|
+
const iconNode = loading ? (
|
|
199
|
+
<ActivityIndicator color={textColor} size={ICON_SIZE} />
|
|
200
|
+
) : (
|
|
201
|
+
renderIcon(icon, textColor, ICON_SIZE)
|
|
202
|
+
);
|
|
203
|
+
|
|
99
204
|
return (
|
|
100
205
|
<PlatformPressable
|
|
101
206
|
{...rest}
|
|
207
|
+
disabled={disabled || loading}
|
|
102
208
|
android_ripple={{
|
|
103
|
-
|
|
104
|
-
color:
|
|
209
|
+
foreground: true,
|
|
210
|
+
color: rippleColor,
|
|
105
211
|
...android_ripple,
|
|
106
212
|
}}
|
|
107
213
|
pressOpacity={Platform.OS === 'ios' ? undefined : 1}
|
|
@@ -110,19 +216,58 @@ function ButtonBase({
|
|
|
110
216
|
}
|
|
111
217
|
style={[{ backgroundColor }, styles.button, style]}
|
|
112
218
|
>
|
|
113
|
-
<
|
|
114
|
-
{
|
|
115
|
-
|
|
219
|
+
<View style={styles.content}>
|
|
220
|
+
{iconNode && <View style={styles.icon}>{iconNode}</View>}
|
|
221
|
+
<Text style={[{ color: textColor }, fonts.regular, styles.text]}>
|
|
222
|
+
{children}
|
|
223
|
+
</Text>
|
|
224
|
+
</View>
|
|
116
225
|
</PlatformPressable>
|
|
117
226
|
);
|
|
118
227
|
}
|
|
119
228
|
|
|
229
|
+
function renderIcon(
|
|
230
|
+
icon: ButtonBaseProps['icon'],
|
|
231
|
+
color: ColorValue,
|
|
232
|
+
size: number
|
|
233
|
+
) {
|
|
234
|
+
if (!icon) {
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const iconValue = typeof icon === 'function' ? icon({ color, size }) : icon;
|
|
239
|
+
|
|
240
|
+
if (React.isValidElement(iconValue)) {
|
|
241
|
+
return iconValue;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (
|
|
245
|
+
typeof iconValue === 'object' &&
|
|
246
|
+
iconValue != null &&
|
|
247
|
+
'type' in iconValue
|
|
248
|
+
) {
|
|
249
|
+
return <PlatformIcon icon={iconValue} size={size} color={color} />;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
|
|
120
255
|
const styles = StyleSheet.create({
|
|
121
256
|
button: {
|
|
122
257
|
paddingHorizontal: 24,
|
|
123
258
|
paddingVertical: 10,
|
|
124
259
|
borderRadius: BUTTON_RADIUS,
|
|
125
260
|
borderCurve: 'continuous',
|
|
261
|
+
overflow: 'hidden',
|
|
262
|
+
},
|
|
263
|
+
content: {
|
|
264
|
+
flexDirection: 'row',
|
|
265
|
+
alignItems: 'center',
|
|
266
|
+
justifyContent: 'center',
|
|
267
|
+
gap: 8,
|
|
268
|
+
},
|
|
269
|
+
icon: {
|
|
270
|
+
marginLeft: -6,
|
|
126
271
|
},
|
|
127
272
|
text: {
|
|
128
273
|
fontSize: 14,
|