Skip to content

Commit e3dbaac

Browse files
feat(react-ui-core): extract core react hooks (#485)
1 parent 949c896 commit e3dbaac

34 files changed

+558
-378
lines changed

.changeset/stupid-forks-leave.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@stackflow/plugin-basic-ui": minor
3+
"@stackflow/react-ui-core": minor
4+
---
5+
6+
Extract core react hooks as a "@stackflow/react-ui-core" package

.pnp.cjs

Lines changed: 50 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extensions/plugin-basic-ui/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"typecheck": "tsc --noEmit"
3333
},
3434
"dependencies": {
35+
"@stackflow/react-ui-core": "^1.0.0",
3536
"@vanilla-extract/css": "^1.15.3",
3637
"@vanilla-extract/dynamic": "^2.1.1",
3738
"@vanilla-extract/private": "^1.0.5",

extensions/plugin-basic-ui/src/components/AppBar.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@ import { useActions } from "@stackflow/react";
22
import { assignInlineVars } from "@vanilla-extract/dynamic";
33
import { forwardRef, useRef } from "react";
44

5+
import {
6+
useAppBarTitleMaxWidth,
7+
useNullableActivity,
8+
} from "@stackflow/react-ui-core";
59
import { IconBack, IconClose } from "../assets";
610
import { useGlobalOptions } from "../basicUIPlugin";
711
import type { GlobalVars } from "../basicUIPlugin.css";
812
import { globalVars } from "../basicUIPlugin.css";
9-
import { useMaxWidth, useNullableActivity } from "../hooks";
13+
1014
import { compactMap } from "../utils";
1115
import * as css from "./AppBar.css";
1216
import * as appScreenCss from "./AppScreen.css";
@@ -92,7 +96,7 @@ const AppBar = forwardRef<HTMLDivElement, AppBarProps>(
9296

9397
const centerRef = useRef<any>(null);
9498

95-
const { maxWidth } = useMaxWidth({
99+
const { maxWidth } = useAppBarTitleMaxWidth({
96100
outerRef: ref,
97101
innerRef: centerRef,
98102
enable: globalOptions.theme === "cupertino",

extensions/plugin-basic-ui/src/components/AppScreen.css.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,14 +129,14 @@ export const paper = recipe({
129129
"@supports": {
130130
"(margin-top: constant(safe-area-inset-top))": {
131131
vars: {
132-
[vars.appBar
133-
.topMargin]: `calc(${globalVars.appBar.height} + max(${globalVars.appBar.minSafeAreaInsetTop}, constant(safe-area-inset-top)))`,
132+
[vars.appBar.topMargin]:
133+
`calc(${globalVars.appBar.height} + max(${globalVars.appBar.minSafeAreaInsetTop}, constant(safe-area-inset-top)))`,
134134
},
135135
},
136136
"(margin-top: env(safe-area-inset-top))": {
137137
vars: {
138-
[vars.appBar
139-
.topMargin]: `calc(${globalVars.appBar.height} + max(${globalVars.appBar.minSafeAreaInsetTop}, env(safe-area-inset-top)))`,
138+
[vars.appBar.topMargin]:
139+
`calc(${globalVars.appBar.height} + max(${globalVars.appBar.minSafeAreaInsetTop}, env(safe-area-inset-top)))`,
140140
},
141141
},
142142
},

extensions/plugin-basic-ui/src/components/AppScreen.tsx

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@ import { useActions } from "@stackflow/react";
22
import { assignInlineVars } from "@vanilla-extract/dynamic";
33
import { createContext, useContext, useMemo, useRef } from "react";
44

5-
import { useGlobalOptions } from "../basicUIPlugin";
6-
import type { GlobalVars } from "../basicUIPlugin.css";
7-
import { globalVars } from "../basicUIPlugin.css";
85
import {
96
useLazy,
107
useMounted,
@@ -13,12 +10,18 @@ import {
1310
useStyleEffectOffset,
1411
useStyleEffectSwipeBack,
1512
useZIndexBase,
16-
} from "../hooks";
13+
} from "@stackflow/react-ui-core";
14+
import { useGlobalOptions } from "../basicUIPlugin";
15+
import type { GlobalVars } from "../basicUIPlugin.css";
16+
import { globalVars } from "../basicUIPlugin.css";
1717
import type { PropOf } from "../utils";
1818
import { compactMap } from "../utils";
1919
import AppBar from "./AppBar";
2020
import * as css from "./AppScreen.css";
2121

22+
export const OFFSET_PX_ANDROID = 32;
23+
export const OFFSET_PX_CUPERTINO = 80;
24+
2225
export type AppScreenContext = {
2326
scroll: (args: { top: number }) => void;
2427
};
@@ -70,7 +73,7 @@ const AppScreen: React.FC<AppScreenProps> = ({
7073
? ANDROID_ONLY_activityEnterStyle
7174
: undefined;
7275

73-
const swipeBackPrevented =
76+
const isSwipeBackPrevented =
7477
preventSwipeBack || modalPresentationStyle === "fullScreen";
7578

7679
const hasAppBar = !!appBar;
@@ -108,28 +111,65 @@ const AppScreen: React.FC<AppScreenProps> = ({
108111

109112
useStyleEffectHide({
110113
refs: [appScreenRef],
111-
hasEffect: true,
112114
});
113115
useStyleEffectOffset({
114116
refs:
115117
globalOptions.theme === "cupertino" ||
116118
activityEnterStyle === "slideInLeft"
117119
? [paperRef]
118120
: [paperRef, appBarRef],
119-
theme: globalOptions.theme,
120-
activityEnterStyle,
121+
offsetStyles:
122+
globalOptions.theme === "cupertino"
123+
? {
124+
transform: `translate3d(-${OFFSET_PX_CUPERTINO / 16}rem, 0, 0)`,
125+
opacity: "1",
126+
}
127+
: activityEnterStyle === "slideInLeft"
128+
? {
129+
transform: "translate3d(-50%, 0, 0)",
130+
opacity: "0",
131+
}
132+
: {
133+
transform: `translate3d(0, -${OFFSET_PX_ANDROID / 16}rem, 0)`,
134+
opacity: "1",
135+
},
136+
transitionDuration: globalVars.computedTransitionDuration,
121137
hasEffect: modalPresentationStyle !== "fullScreen",
122138
});
123139
useStyleEffectSwipeBack({
124140
dimRef,
125141
edgeRef,
126142
paperRef,
127-
theme: globalOptions.theme,
128-
prevented: swipeBackPrevented,
143+
offset: OFFSET_PX_CUPERTINO,
144+
transitionDuration: globalVars.transitionDuration,
145+
preventSwipeBack:
146+
isSwipeBackPrevented || globalOptions.theme !== "cupertino",
147+
getActivityTransitionState() {
148+
const $paper = paperRef.current;
149+
const $appScreen = $paper?.parentElement;
150+
151+
if (!$appScreen) {
152+
return null;
153+
}
154+
155+
if ($appScreen.classList.contains(css.enterActive)) {
156+
return "enter-active";
157+
}
158+
if ($appScreen.classList.contains(css.enterDone)) {
159+
return "enter-done";
160+
}
161+
if ($appScreen.classList.contains(css.exitActive)) {
162+
return "exit-active";
163+
}
164+
if ($appScreen.classList.contains(css.exitDone)) {
165+
return "exit-done";
166+
}
167+
168+
return null;
169+
},
129170
onSwiped() {
130171
pop();
131172
},
132-
hasEffect: true,
133173
});
134174

135175
const onAppBarTopClick: React.MouseEventHandler = (e) => {
@@ -214,14 +254,12 @@ const AppScreen: React.FC<AppScreenProps> = ({
214254
</div>
215255
{!activity?.isRoot &&
216256
globalOptions.theme === "cupertino" &&
217-
!swipeBackPrevented && (
257+
!isSwipeBackPrevented && (
218258
<div className={css.edge({ hasAppBar })} ref={edgeRef} />
219259
)}
220260
</div>
221261
</Context.Provider>
222262
);
223263
};
224264

225-
AppScreen.displayName = "AppScreen";
226-
227265
export default AppScreen;

extensions/plugin-basic-ui/src/components/BottomSheet.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ import { useActions } from "@stackflow/react";
22
import { assignInlineVars } from "@vanilla-extract/dynamic";
33
import { useRef } from "react";
44

5-
import type { GlobalVars } from "../basicUIPlugin.css";
6-
import { globalVars } from "../basicUIPlugin.css";
75
import {
86
useLazy,
97
useNullableActivity,
108
useStyleEffect,
119
useZIndexBase,
12-
} from "../hooks";
10+
} from "@stackflow/react-ui-core";
11+
import type { GlobalVars } from "../basicUIPlugin.css";
12+
import { globalVars } from "../basicUIPlugin.css";
1313
import { compactMap } from "../utils";
1414
import * as css from "./BottomSheet.css";
1515

extensions/plugin-basic-ui/src/components/Modal.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ import { useActions } from "@stackflow/react";
22
import { assignInlineVars } from "@vanilla-extract/dynamic";
33
import { useRef } from "react";
44

5-
import type { GlobalVars } from "../basicUIPlugin.css";
6-
import { globalVars } from "../basicUIPlugin.css";
75
import {
86
useLazy,
97
useNullableActivity,
108
useStyleEffect,
119
useZIndexBase,
12-
} from "../hooks";
10+
} from "@stackflow/react-ui-core";
11+
import type { GlobalVars } from "../basicUIPlugin.css";
12+
import { globalVars } from "../basicUIPlugin.css";
1313
import { compactMap } from "../utils";
1414
import * as css from "./Modal.css";
1515

extensions/plugin-basic-ui/src/hooks/useStyleEffectHide.ts

Lines changed: 0 additions & 51 deletions
This file was deleted.

0 commit comments

Comments
 (0)