@stackflow/plugin-basic-ui 0.19.3-alpha.1 → 0.20.1
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/dist/basicUIPlugin.d.ts +1 -0
- package/dist/components/AppBar.css.d.ts +3 -1
- package/dist/components/AppBar.d.ts +3 -2
- package/dist/components/AppScreen.css.d.ts +2 -2
- package/dist/components/AppScreen.d.ts +7 -3
- package/dist/components/BottomSheet.d.ts +1 -1
- package/dist/components/Modal.d.ts +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/useNullableActivity.d.ts +2 -0
- package/dist/index.css +409 -1
- package/dist/index.css.map +3 -3
- package/dist/index.d.ts +3 -4
- package/dist/index.js +1009 -1
- package/dist/index.js.map +4 -4
- package/dist/index.mjs +987 -1
- package/dist/index.mjs.map +4 -4
- package/dist/styles/f.css.d.ts +1 -0
- package/dist/theme.css.d.ts +2 -1
- package/dist/utils/compact.d.ts +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/package.json +6 -7
- package/src/basicUIPlugin.tsx +5 -2
- package/src/components/AppBar.css.ts +29 -21
- package/src/components/AppBar.tsx +41 -33
- package/src/components/AppScreen.css.ts +11 -10
- package/src/components/AppScreen.tsx +72 -50
- package/src/components/BottomSheet.css.ts +5 -4
- package/src/components/BottomSheet.tsx +12 -9
- package/src/components/Modal.css.ts +2 -1
- package/src/components/Modal.tsx +12 -9
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useNullableActivity.ts +6 -0
- package/src/hooks/useStyleEffect.ts +11 -4
- package/src/hooks/useStyleEffectOffset.ts +2 -2
- package/src/hooks/useStyleEffectSwipeBack.ts +5 -5
- package/src/index.ts +10 -8
- package/src/styles/f.css.ts +4 -0
- package/src/theme.css.ts +5 -2
- package/src/utils/compact.ts +6 -0
- package/src/utils/index.ts +1 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { useActions
|
|
1
|
+
import { useActions } from "@stackflow/react";
|
|
2
2
|
import { assignInlineVars } from "@vanilla-extract/dynamic";
|
|
3
3
|
import React, { useRef } from "react";
|
|
4
4
|
|
|
5
5
|
import { IconBack, IconClose } from "../assets";
|
|
6
6
|
import { useGlobalOptions } from "../basicUIPlugin";
|
|
7
|
-
import { useMaxWidth } from "../hooks";
|
|
7
|
+
import { useMaxWidth, useNullableActivity } from "../hooks";
|
|
8
8
|
import type { GlobalVars } from "../theme.css";
|
|
9
9
|
import { globalVars } from "../theme.css";
|
|
10
10
|
import { compactMap, noop } from "../utils";
|
|
@@ -17,6 +17,7 @@ type AppBarProps = Partial<
|
|
|
17
17
|
| "borderColor"
|
|
18
18
|
| "borderSize"
|
|
19
19
|
| "height"
|
|
20
|
+
| "heightTransitionDuration"
|
|
20
21
|
| "iconColor"
|
|
21
22
|
| "textColor"
|
|
22
23
|
| "backgroundColor"
|
|
@@ -66,7 +67,7 @@ const AppBar = React.forwardRef<HTMLDivElement, AppBarProps>(
|
|
|
66
67
|
ref,
|
|
67
68
|
) => {
|
|
68
69
|
const actions = useActions();
|
|
69
|
-
const activity =
|
|
70
|
+
const activity = useNullableActivity();
|
|
70
71
|
|
|
71
72
|
const globalOptions = useGlobalOptions();
|
|
72
73
|
const globalCloseButton = globalOptions.appBar?.closeButton;
|
|
@@ -90,6 +91,9 @@ const AppBar = React.forwardRef<HTMLDivElement, AppBarProps>(
|
|
|
90
91
|
};
|
|
91
92
|
|
|
92
93
|
const renderBackButton = () => {
|
|
94
|
+
if (!activity) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
93
97
|
if (activity.isRoot) {
|
|
94
98
|
return null;
|
|
95
99
|
}
|
|
@@ -136,10 +140,9 @@ const AppBar = React.forwardRef<HTMLDivElement, AppBarProps>(
|
|
|
136
140
|
};
|
|
137
141
|
|
|
138
142
|
const renderCloseButton = () => {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
) {
|
|
143
|
+
const isRoot = !activity || activity.isRoot;
|
|
144
|
+
|
|
145
|
+
if ((!closeButton && !globalOptions.appBar?.closeButton) || !isRoot) {
|
|
143
146
|
return null;
|
|
144
147
|
}
|
|
145
148
|
if (closeButton && "render" in closeButton && closeButton.render) {
|
|
@@ -206,37 +209,42 @@ const AppBar = React.forwardRef<HTMLDivElement, AppBarProps>(
|
|
|
206
209
|
}),
|
|
207
210
|
)}
|
|
208
211
|
>
|
|
209
|
-
<div className={css.
|
|
210
|
-
|
|
211
|
-
{
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
212
|
+
<div className={css.safeArea} />
|
|
213
|
+
<div className={css.container}>
|
|
214
|
+
<div className={css.left}>
|
|
215
|
+
{closeButtonLocation === "left" && renderCloseButton()}
|
|
216
|
+
{renderBackButton()}
|
|
217
|
+
{appendLeft?.()}
|
|
218
|
+
</div>
|
|
219
|
+
<div ref={centerRef} className={css.center}>
|
|
220
|
+
<div
|
|
221
|
+
className={css.centerMain({
|
|
222
|
+
hasLeft,
|
|
223
|
+
})}
|
|
224
|
+
>
|
|
225
|
+
{typeof title === "string" ? (
|
|
226
|
+
<div className={css.centerText}>{title}</div>
|
|
227
|
+
) : (
|
|
228
|
+
title
|
|
229
|
+
)}
|
|
230
|
+
<button
|
|
231
|
+
className={css.centerMainEdge}
|
|
232
|
+
type="button"
|
|
233
|
+
aria-hidden="true"
|
|
234
|
+
onClick={onTopClick}
|
|
235
|
+
/>
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
238
|
+
<div className={css.right}>
|
|
239
|
+
{appendRight?.()}
|
|
240
|
+
{closeButtonLocation === "right" && renderCloseButton()}
|
|
231
241
|
</div>
|
|
232
|
-
</div>
|
|
233
|
-
<div className={css.right}>
|
|
234
|
-
{appendRight?.()}
|
|
235
|
-
{closeButtonLocation === "right" && renderCloseButton()}
|
|
236
242
|
</div>
|
|
237
243
|
</div>
|
|
238
244
|
);
|
|
239
245
|
},
|
|
240
246
|
);
|
|
241
247
|
|
|
248
|
+
AppBar.displayName = "AppBar";
|
|
249
|
+
|
|
242
250
|
export default AppBar;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { createThemeContract, style } from "@vanilla-extract/css";
|
|
2
|
-
import { calc } from "@vanilla-extract/css-utils";
|
|
3
2
|
import { recipe } from "@vanilla-extract/recipes";
|
|
4
3
|
|
|
5
4
|
import { f } from "../styles";
|
|
@@ -42,7 +41,7 @@ export const enterActive = style({});
|
|
|
42
41
|
export const enterDone = style({});
|
|
43
42
|
export const exitActive = style({});
|
|
44
43
|
export const exitDone = style({
|
|
45
|
-
transform: "
|
|
44
|
+
transform: "translate3d(100%, 0, 0)",
|
|
46
45
|
});
|
|
47
46
|
|
|
48
47
|
export const appScreen = recipe({
|
|
@@ -64,6 +63,7 @@ export const dim = style([
|
|
|
64
63
|
{
|
|
65
64
|
opacity: 0,
|
|
66
65
|
zIndex: vars.zIndexes.dim,
|
|
66
|
+
willChange: "opacity",
|
|
67
67
|
selectors: {
|
|
68
68
|
[`${android} &, ${rootAndroid} &`]: {
|
|
69
69
|
height: "10rem",
|
|
@@ -97,27 +97,28 @@ export const paper = recipe({
|
|
|
97
97
|
display: "none",
|
|
98
98
|
},
|
|
99
99
|
zIndex: vars.zIndexes.paper,
|
|
100
|
+
willChange: "transform",
|
|
100
101
|
selectors: {
|
|
101
102
|
[`${cupertino} &, ${rootCupertino} &`]: {
|
|
102
|
-
transform: "
|
|
103
|
+
transform: "translate3d(100%, 0, 0)",
|
|
103
104
|
},
|
|
104
105
|
[`${cupertino} ${enterActive} &, ${rootCupertino} ${enterActive} &`]: {
|
|
105
|
-
transform: "
|
|
106
|
+
transform: "translate3d(0, 0, 0)",
|
|
106
107
|
},
|
|
107
108
|
[`${cupertino} ${enterDone} &, ${rootCupertino} ${enterDone} &`]: {
|
|
108
|
-
transform: "
|
|
109
|
+
transform: "translate3d(0, 0, 0)",
|
|
109
110
|
},
|
|
110
111
|
[`${android} &, ${rootAndroid} &`]: {
|
|
111
112
|
opacity: 0,
|
|
112
|
-
transform: "
|
|
113
|
+
transform: "translate3d(0, 10rem, 0)",
|
|
113
114
|
},
|
|
114
115
|
[`${android} ${enterActive} &, ${rootAndroid} ${enterActive} &`]: {
|
|
115
116
|
opacity: 1,
|
|
116
|
-
transform: "
|
|
117
|
+
transform: "translate3d(0, 0, 0)",
|
|
117
118
|
},
|
|
118
119
|
[`${android} ${enterDone} &, ${rootAndroid} ${enterDone} &`]: {
|
|
119
120
|
opacity: 1,
|
|
120
|
-
transform: "
|
|
121
|
+
transform: "translate3d(0, 0, 0)",
|
|
121
122
|
},
|
|
122
123
|
},
|
|
123
124
|
},
|
|
@@ -127,7 +128,7 @@ export const paper = recipe({
|
|
|
127
128
|
true: [
|
|
128
129
|
f.borderBox,
|
|
129
130
|
{
|
|
130
|
-
transition: `transform ${vars.transitionDuration}, opacity ${vars.transitionDuration},
|
|
131
|
+
transition: `transform ${vars.transitionDuration}, opacity ${vars.transitionDuration}, padding-top ${globalVars.appBar.heightTransitionDuration}`,
|
|
131
132
|
paddingTop: [
|
|
132
133
|
`calc(${globalVars.appBar.height} + constant(safe-area-inset-top))`,
|
|
133
134
|
`calc(${globalVars.appBar.height} + env(safe-area-inset-top))`,
|
|
@@ -153,7 +154,7 @@ export const edge = recipe({
|
|
|
153
154
|
hasAppBar: {
|
|
154
155
|
true: {
|
|
155
156
|
top: globalVars.appBar.height,
|
|
156
|
-
height: calc(
|
|
157
|
+
height: `calc(100% - ${globalVars.appBar.height})`,
|
|
157
158
|
},
|
|
158
159
|
},
|
|
159
160
|
},
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/* eslint-disable no-param-reassign */
|
|
2
2
|
|
|
3
|
-
import { useActions
|
|
3
|
+
import { useActions } from "@stackflow/react";
|
|
4
4
|
import { assignInlineVars } from "@vanilla-extract/dynamic";
|
|
5
|
-
import React, { useRef } from "react";
|
|
5
|
+
import React, { createContext, useContext, useMemo, useRef } from "react";
|
|
6
6
|
|
|
7
7
|
import { useGlobalOptions } from "../basicUIPlugin";
|
|
8
8
|
import {
|
|
9
9
|
useLazy,
|
|
10
|
+
useNullableActivity,
|
|
10
11
|
useStyleEffectHide,
|
|
11
12
|
useStyleEffectOffset,
|
|
12
13
|
useStyleEffectSwipeBack,
|
|
@@ -18,12 +19,19 @@ import { compactMap } from "../utils";
|
|
|
18
19
|
import AppBar from "./AppBar";
|
|
19
20
|
import * as css from "./AppScreen.css";
|
|
20
21
|
|
|
21
|
-
type
|
|
22
|
+
export type AppScreenContext = {
|
|
23
|
+
scroll: (args: { top: number }) => void;
|
|
24
|
+
};
|
|
25
|
+
const Context = createContext<AppScreenContext>(null as any);
|
|
26
|
+
|
|
27
|
+
export function useAppScreen() {
|
|
28
|
+
return useContext(Context);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type AppScreenProps = Partial<
|
|
22
32
|
Pick<GlobalVars, "backgroundColor" | "dimBackgroundColor">
|
|
23
33
|
> & {
|
|
24
34
|
appBar?: Omit<PropOf<typeof AppBar>, "theme" | "ref" | "key">;
|
|
25
|
-
showAppBar?: boolean;
|
|
26
|
-
showAppBarTransitionDuration?: string;
|
|
27
35
|
preventSwipeBack?: boolean;
|
|
28
36
|
children: React.ReactNode;
|
|
29
37
|
};
|
|
@@ -31,13 +39,11 @@ const AppScreen: React.FC<AppScreenProps> = ({
|
|
|
31
39
|
backgroundColor,
|
|
32
40
|
dimBackgroundColor,
|
|
33
41
|
appBar,
|
|
34
|
-
showAppBar = !!appBar,
|
|
35
|
-
showAppBarTransitionDuration,
|
|
36
42
|
preventSwipeBack,
|
|
37
43
|
children,
|
|
38
44
|
}) => {
|
|
39
45
|
const globalOptions = useGlobalOptions();
|
|
40
|
-
const activity =
|
|
46
|
+
const activity = useNullableActivity();
|
|
41
47
|
const { pop } = useActions();
|
|
42
48
|
|
|
43
49
|
const appScreenRef = useRef<HTMLDivElement>(null);
|
|
@@ -67,16 +73,16 @@ const AppScreen: React.FC<AppScreenProps> = ({
|
|
|
67
73
|
},
|
|
68
74
|
});
|
|
69
75
|
|
|
70
|
-
const hasAppBar = !!appBar
|
|
76
|
+
const hasAppBar = !!appBar;
|
|
71
77
|
|
|
72
|
-
const zIndexBase = activity
|
|
78
|
+
const zIndexBase = (activity?.zIndex ?? 0) * 5;
|
|
73
79
|
const zIndexDim = zIndexBase;
|
|
74
80
|
const zIndexPaper =
|
|
75
81
|
zIndexBase + (globalOptions.theme === "cupertino" && hasAppBar ? 1 : 3);
|
|
76
82
|
const zIndexEdge = zIndexBase + 4;
|
|
77
83
|
const zIndexAppBar = zIndexBase + 7;
|
|
78
84
|
|
|
79
|
-
const
|
|
85
|
+
const transitionState = activity?.transitionState ?? "enter-done";
|
|
80
86
|
const lazyTransitionState = useLazy(transitionState);
|
|
81
87
|
|
|
82
88
|
const onAppBarTopClick: React.MouseEventHandler = (e) => {
|
|
@@ -91,53 +97,69 @@ const AppScreen: React.FC<AppScreenProps> = ({
|
|
|
91
97
|
};
|
|
92
98
|
|
|
93
99
|
return (
|
|
94
|
-
<
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
compactMap({
|
|
104
|
-
[globalVars.backgroundColor]: backgroundColor,
|
|
105
|
-
[globalVars.dimBackgroundColor]: dimBackgroundColor,
|
|
106
|
-
[globalVars.appBar.height]: showAppBar ? appBar?.height : "0",
|
|
107
|
-
[globalVars.appBar.showTransitionDuration]:
|
|
108
|
-
showAppBarTransitionDuration,
|
|
109
|
-
[css.vars.zIndexes.dim]: `${zIndexDim}`,
|
|
110
|
-
[css.vars.zIndexes.paper]: `${zIndexPaper}`,
|
|
111
|
-
[css.vars.zIndexes.edge]: `${zIndexEdge}`,
|
|
112
|
-
[css.vars.zIndexes.appBar]: `${zIndexAppBar}`,
|
|
113
|
-
[css.vars.transitionDuration]:
|
|
114
|
-
activity.transitionState === "enter-active" ||
|
|
115
|
-
activity.transitionState === "exit-active"
|
|
116
|
-
? `var(--stackflow-transition-duration)`
|
|
117
|
-
: "0ms",
|
|
100
|
+
<Context.Provider
|
|
101
|
+
value={useMemo(
|
|
102
|
+
() => ({
|
|
103
|
+
scroll({ top }) {
|
|
104
|
+
paperRef?.current?.scroll({
|
|
105
|
+
top,
|
|
106
|
+
behavior: "smooth",
|
|
107
|
+
});
|
|
108
|
+
},
|
|
118
109
|
}),
|
|
110
|
+
[paperRef],
|
|
119
111
|
)}
|
|
120
112
|
>
|
|
121
|
-
<div className={css.dim} ref={dimRef} />
|
|
122
113
|
<div
|
|
123
|
-
|
|
124
|
-
className={css.
|
|
125
|
-
|
|
114
|
+
ref={appScreenRef}
|
|
115
|
+
className={css.appScreen({
|
|
116
|
+
transitionState:
|
|
117
|
+
transitionState === "enter-done" || transitionState === "exit-done"
|
|
118
|
+
? transitionState
|
|
119
|
+
: lazyTransitionState,
|
|
126
120
|
})}
|
|
127
|
-
|
|
121
|
+
style={assignInlineVars(
|
|
122
|
+
compactMap({
|
|
123
|
+
[globalVars.backgroundColor]: backgroundColor,
|
|
124
|
+
[globalVars.dimBackgroundColor]: dimBackgroundColor,
|
|
125
|
+
[globalVars.appBar.height]: appBar?.height,
|
|
126
|
+
[globalVars.appBar.heightTransitionDuration]:
|
|
127
|
+
appBar?.heightTransitionDuration,
|
|
128
|
+
[css.vars.zIndexes.dim]: `${zIndexDim}`,
|
|
129
|
+
[css.vars.zIndexes.paper]: `${zIndexPaper}`,
|
|
130
|
+
[css.vars.zIndexes.edge]: `${zIndexEdge}`,
|
|
131
|
+
[css.vars.zIndexes.appBar]: `${zIndexAppBar}`,
|
|
132
|
+
[css.vars.transitionDuration]:
|
|
133
|
+
transitionState === "enter-active" ||
|
|
134
|
+
transitionState === "exit-active"
|
|
135
|
+
? `var(--stackflow-transition-duration)`
|
|
136
|
+
: "0ms",
|
|
137
|
+
}),
|
|
138
|
+
)}
|
|
128
139
|
>
|
|
129
|
-
{
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
140
|
+
<div className={css.dim} ref={dimRef} />
|
|
141
|
+
<div
|
|
142
|
+
key={activity?.id}
|
|
143
|
+
className={css.paper({
|
|
144
|
+
hasAppBar,
|
|
145
|
+
})}
|
|
146
|
+
ref={paperRef}
|
|
147
|
+
>
|
|
148
|
+
{children}
|
|
149
|
+
</div>
|
|
150
|
+
{!activity?.isRoot &&
|
|
151
|
+
globalOptions.theme === "cupertino" &&
|
|
152
|
+
!preventSwipeBack && (
|
|
153
|
+
<div className={css.edge({ hasAppBar })} ref={edgeRef} />
|
|
154
|
+
)}
|
|
155
|
+
{appBar && (
|
|
156
|
+
<AppBar {...appBar} ref={appBarRef} onTopClick={onAppBarTopClick} />
|
|
135
157
|
)}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
)}
|
|
139
|
-
</div>
|
|
158
|
+
</div>
|
|
159
|
+
</Context.Provider>
|
|
140
160
|
);
|
|
141
161
|
};
|
|
142
162
|
|
|
163
|
+
AppScreen.displayName = "AppScreen";
|
|
164
|
+
|
|
143
165
|
export default AppScreen;
|
|
@@ -20,7 +20,7 @@ export const enterActive = style({});
|
|
|
20
20
|
export const enterDone = style({});
|
|
21
21
|
export const exitActive = style({});
|
|
22
22
|
export const exitDone = style({
|
|
23
|
-
transform: "
|
|
23
|
+
transform: "translate3d(100%, 0, 0)",
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
export const container = recipe({
|
|
@@ -62,15 +62,16 @@ export const paper = style([
|
|
|
62
62
|
backgroundColor: globalVars.backgroundColor,
|
|
63
63
|
width: "100%",
|
|
64
64
|
borderRadius: `${globalVars.bottomSheet.borderRadius} ${globalVars.bottomSheet.borderRadius} 0 0`,
|
|
65
|
-
|
|
65
|
+
willChange: "transform, opacity",
|
|
66
|
+
transform: "translate3d(0, 100%, 0)",
|
|
66
67
|
opacity: 0,
|
|
67
68
|
selectors: {
|
|
68
69
|
[`${enterActive} &, ${enterDone} &`]: {
|
|
69
|
-
transform: "
|
|
70
|
+
transform: "translate3d(0, 0, 0)",
|
|
70
71
|
opacity: 1,
|
|
71
72
|
},
|
|
72
73
|
[`${exitActive} &, ${exitDone} &`]: {
|
|
73
|
-
transform: "
|
|
74
|
+
transform: "translate3d(0, 100%, 0)",
|
|
74
75
|
opacity: 0,
|
|
75
76
|
},
|
|
76
77
|
},
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/* eslint-disable jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */
|
|
2
2
|
|
|
3
|
-
import { useActions
|
|
3
|
+
import { useActions } from "@stackflow/react";
|
|
4
4
|
import { assignInlineVars } from "@vanilla-extract/dynamic";
|
|
5
5
|
import React, { useRef } from "react";
|
|
6
6
|
|
|
7
|
-
import { useLazy, useStyleEffect } from "../hooks";
|
|
7
|
+
import { useLazy, useNullableActivity, useStyleEffect } from "../hooks";
|
|
8
8
|
import type { GlobalVars } from "../theme.css";
|
|
9
9
|
import { globalVars } from "../theme.css";
|
|
10
10
|
import { compactMap } from "../utils";
|
|
11
11
|
import * as css from "./BottomSheet.css";
|
|
12
12
|
|
|
13
|
-
type BottomSheetProps = Partial<
|
|
13
|
+
export type BottomSheetProps = Partial<
|
|
14
14
|
Pick<GlobalVars, "backgroundColor" | "dimBackgroundColor">
|
|
15
15
|
> &
|
|
16
16
|
Partial<GlobalVars["bottomSheet"]> & {
|
|
@@ -24,7 +24,7 @@ const BottomSheet: React.FC<BottomSheetProps> = ({
|
|
|
24
24
|
onOutsideClick,
|
|
25
25
|
children,
|
|
26
26
|
}) => {
|
|
27
|
-
const activity =
|
|
27
|
+
const activity = useNullableActivity();
|
|
28
28
|
const { pop } = useActions();
|
|
29
29
|
|
|
30
30
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
@@ -63,13 +63,14 @@ const BottomSheet: React.FC<BottomSheetProps> = ({
|
|
|
63
63
|
e.stopPropagation();
|
|
64
64
|
};
|
|
65
65
|
|
|
66
|
-
const zIndexBase = activity
|
|
67
|
-
const zIndexPaper = activity
|
|
66
|
+
const zIndexBase = (activity?.zIndex ?? 0) * 5 + 3;
|
|
67
|
+
const zIndexPaper = (activity?.zIndex ?? 0) * 5 + 4;
|
|
68
|
+
const transitionState = activity?.transitionState ?? "enter-done";
|
|
68
69
|
|
|
69
70
|
return (
|
|
70
71
|
<div
|
|
71
72
|
className={css.container({
|
|
72
|
-
transitionState: useLazy(
|
|
73
|
+
transitionState: useLazy(transitionState),
|
|
73
74
|
})}
|
|
74
75
|
ref={containerRef}
|
|
75
76
|
style={assignInlineVars(
|
|
@@ -80,8 +81,8 @@ const BottomSheet: React.FC<BottomSheetProps> = ({
|
|
|
80
81
|
[css.vars.zIndexes.dim]: `${zIndexBase}`,
|
|
81
82
|
[css.vars.zIndexes.paper]: `${zIndexPaper}`,
|
|
82
83
|
[css.vars.transitionDuration]:
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
transitionState === "enter-active" ||
|
|
85
|
+
transitionState === "exit-active"
|
|
85
86
|
? `var(--stackflow-transition-duration)`
|
|
86
87
|
: "0ms",
|
|
87
88
|
}),
|
|
@@ -96,4 +97,6 @@ const BottomSheet: React.FC<BottomSheetProps> = ({
|
|
|
96
97
|
);
|
|
97
98
|
};
|
|
98
99
|
|
|
100
|
+
BottomSheet.displayName = "BottomSheet";
|
|
101
|
+
|
|
99
102
|
export default BottomSheet;
|
|
@@ -20,7 +20,7 @@ export const enterActive = style({});
|
|
|
20
20
|
export const enterDone = style({});
|
|
21
21
|
export const exitActive = style({});
|
|
22
22
|
export const exitDone = style({
|
|
23
|
-
transform: "
|
|
23
|
+
transform: "translate3d(100%, 0, 0)",
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
export const container = recipe({
|
|
@@ -66,6 +66,7 @@ export const paper = style([
|
|
|
66
66
|
boxShadow:
|
|
67
67
|
"0px 0.625rem 2.375rem rgba(0, 0, 0, 0.15), 0px .5625rem 2.875rem rgba(0, 0, 0, 0.12), 0px .3125rem .9375rem rgba(0, 0, 0, 0.1)",
|
|
68
68
|
borderRadius: globalVars.modal.borderRadius,
|
|
69
|
+
willChange: "transform, opacity",
|
|
69
70
|
transform: "scale(1.1)",
|
|
70
71
|
opacity: 0,
|
|
71
72
|
selectors: {
|
package/src/components/Modal.tsx
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/* eslint-disable jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */
|
|
2
2
|
|
|
3
|
-
import { useActions
|
|
3
|
+
import { useActions } from "@stackflow/react";
|
|
4
4
|
import { assignInlineVars } from "@vanilla-extract/dynamic";
|
|
5
5
|
import React, { useRef } from "react";
|
|
6
6
|
|
|
7
|
-
import { useLazy, useStyleEffect } from "../hooks";
|
|
7
|
+
import { useLazy, useNullableActivity, useStyleEffect } from "../hooks";
|
|
8
8
|
import type { GlobalVars } from "../theme.css";
|
|
9
9
|
import { globalVars } from "../theme.css";
|
|
10
10
|
import { compactMap } from "../utils";
|
|
11
11
|
import * as css from "./Modal.css";
|
|
12
12
|
|
|
13
|
-
type ModalProps = Partial<
|
|
13
|
+
export type ModalProps = Partial<
|
|
14
14
|
Pick<GlobalVars, "backgroundColor" | "dimBackgroundColor">
|
|
15
15
|
> &
|
|
16
16
|
Partial<GlobalVars["modal"]> & {
|
|
@@ -24,7 +24,7 @@ const Modal: React.FC<ModalProps> = ({
|
|
|
24
24
|
onOutsideClick,
|
|
25
25
|
children,
|
|
26
26
|
}) => {
|
|
27
|
-
const activity =
|
|
27
|
+
const activity = useNullableActivity();
|
|
28
28
|
const { pop } = useActions();
|
|
29
29
|
|
|
30
30
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
@@ -63,13 +63,14 @@ const Modal: React.FC<ModalProps> = ({
|
|
|
63
63
|
e.stopPropagation();
|
|
64
64
|
};
|
|
65
65
|
|
|
66
|
-
const zIndexBase = activity
|
|
67
|
-
const zIndexPaper = activity
|
|
66
|
+
const zIndexBase = (activity?.zIndex ?? 0) * 5 + 3;
|
|
67
|
+
const zIndexPaper = (activity?.zIndex ?? 0) * 5 + 4;
|
|
68
|
+
const transitionState = activity?.transitionState ?? "enter-done";
|
|
68
69
|
|
|
69
70
|
return (
|
|
70
71
|
<div
|
|
71
72
|
className={css.container({
|
|
72
|
-
transitionState: useLazy(
|
|
73
|
+
transitionState: useLazy(transitionState),
|
|
73
74
|
})}
|
|
74
75
|
ref={containerRef}
|
|
75
76
|
style={assignInlineVars(
|
|
@@ -80,8 +81,8 @@ const Modal: React.FC<ModalProps> = ({
|
|
|
80
81
|
[css.vars.zIndexes.dim]: `${zIndexBase}`,
|
|
81
82
|
[css.vars.zIndexes.paper]: `${zIndexPaper}`,
|
|
82
83
|
[css.vars.transitionDuration]:
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
transitionState === "enter-active" ||
|
|
85
|
+
transitionState === "exit-active"
|
|
85
86
|
? `var(--stackflow-transition-duration)`
|
|
86
87
|
: "0ms",
|
|
87
88
|
}),
|
|
@@ -96,4 +97,6 @@ const Modal: React.FC<ModalProps> = ({
|
|
|
96
97
|
);
|
|
97
98
|
};
|
|
98
99
|
|
|
100
|
+
Modal.displayName = "Modal";
|
|
101
|
+
|
|
99
102
|
export default Modal;
|
package/src/hooks/index.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { ActivityTransitionState } from "@stackflow/core";
|
|
2
|
-
import { useActivity } from "@stackflow/react";
|
|
3
2
|
import type React from "react";
|
|
4
3
|
import { useEffect } from "react";
|
|
5
4
|
|
|
5
|
+
import { useNullableActivity } from "./useNullableActivity";
|
|
6
|
+
|
|
6
7
|
const connections: {
|
|
7
8
|
[styleName: string]: Map<
|
|
8
9
|
number,
|
|
@@ -25,9 +26,12 @@ export function useStyleEffect({
|
|
|
25
26
|
refs: Array<React.RefObject<HTMLElement>>;
|
|
26
27
|
}) => (() => void) | void;
|
|
27
28
|
}) {
|
|
28
|
-
const activity =
|
|
29
|
+
const activity = useNullableActivity();
|
|
29
30
|
|
|
30
31
|
useEffect(() => {
|
|
32
|
+
if (!activity) {
|
|
33
|
+
return () => {};
|
|
34
|
+
}
|
|
31
35
|
if (!connections[styleName]) {
|
|
32
36
|
connections[styleName] = new Map();
|
|
33
37
|
}
|
|
@@ -40,9 +44,12 @@ export function useStyleEffect({
|
|
|
40
44
|
return () => {
|
|
41
45
|
connections[styleName].delete(activity.zIndex);
|
|
42
46
|
};
|
|
43
|
-
}, [activity
|
|
47
|
+
}, [activity?.id, refs, effect]);
|
|
44
48
|
|
|
45
49
|
useEffect(() => {
|
|
50
|
+
if (!activity) {
|
|
51
|
+
return () => {};
|
|
52
|
+
}
|
|
46
53
|
if (!effect) {
|
|
47
54
|
return () => {};
|
|
48
55
|
}
|
|
@@ -72,5 +79,5 @@ export function useStyleEffect({
|
|
|
72
79
|
return () => {
|
|
73
80
|
cleanup?.();
|
|
74
81
|
};
|
|
75
|
-
}, [activity
|
|
82
|
+
}, [activity?.transitionState]);
|
|
76
83
|
}
|
|
@@ -22,8 +22,8 @@ export function useStyleEffectOffset({
|
|
|
22
22
|
? ({ activityTransitionState, refs }) => {
|
|
23
23
|
const transform =
|
|
24
24
|
theme === "cupertino"
|
|
25
|
-
? `
|
|
26
|
-
: `
|
|
25
|
+
? `translate3d(-${OFFSET_PX_CUPERTINO / 16}rem, 0, 0)`
|
|
26
|
+
: `translate3d(0, -${OFFSET_PX_ANDROID / 16}rem, 0)`;
|
|
27
27
|
|
|
28
28
|
const cleanup = () => {
|
|
29
29
|
requestNextFrame(() => {
|
|
@@ -72,7 +72,7 @@ export function useStyleEffectSwipeBack({
|
|
|
72
72
|
$dim.style.transition = "0s";
|
|
73
73
|
|
|
74
74
|
$paper.style.overflowY = "hidden";
|
|
75
|
-
$paper.style.transform = `
|
|
75
|
+
$paper.style.transform = `translate3d(${dx}px, 0, 0)`;
|
|
76
76
|
$paper.style.transition = "0s";
|
|
77
77
|
|
|
78
78
|
refs.forEach((ref) => {
|
|
@@ -80,9 +80,9 @@ export function useStyleEffectSwipeBack({
|
|
|
80
80
|
return;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
ref.current.style.transform = `
|
|
83
|
+
ref.current.style.transform = `translate3d(${
|
|
84
84
|
-1 * (1 - p) * OFFSET_PX_CUPERTINO
|
|
85
|
-
}px)`;
|
|
85
|
+
}px, 0, 0)`;
|
|
86
86
|
ref.current.style.transition = "0s";
|
|
87
87
|
|
|
88
88
|
if (ref.current.parentElement?.style.display === "none") {
|
|
@@ -112,9 +112,9 @@ export function useStyleEffectSwipeBack({
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
ref.current.style.transition = `var(--stackflow-transition-duration)`;
|
|
115
|
-
ref.current.style.transform = `
|
|
115
|
+
ref.current.style.transform = `translate3d(${
|
|
116
116
|
swiped ? "0" : `-${OFFSET_PX_CUPERTINO / 16}rem`
|
|
117
|
-
})`;
|
|
117
|
+
}, 0, 0)`;
|
|
118
118
|
});
|
|
119
119
|
|
|
120
120
|
const _cachedRefs = [...cachedRefs];
|