@stackflow/plugin-basic-ui 0.14.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.
Files changed (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +61 -0
  3. package/dist/assets/IconBack.d.ts +5 -0
  4. package/dist/assets/IconClose.d.ts +5 -0
  5. package/dist/assets/index.d.ts +2 -0
  6. package/dist/basicUIPlugin.d.ts +10 -0
  7. package/dist/components/AppBar.css.d.ts +24 -0
  8. package/dist/components/AppBar.d.ts +27 -0
  9. package/dist/components/AppScreen.css.d.ts +44 -0
  10. package/dist/components/AppScreen.d.ts +10 -0
  11. package/dist/components/BottomSheet.css.d.ts +21 -0
  12. package/dist/components/BottomSheet.d.ts +7 -0
  13. package/dist/components/Modal.css.d.ts +21 -0
  14. package/dist/components/Modal.d.ts +7 -0
  15. package/dist/hooks/index.d.ts +7 -0
  16. package/dist/hooks/useLazy.d.ts +1 -0
  17. package/dist/hooks/useMaxWidth.d.ts +8 -0
  18. package/dist/hooks/useStyleEffect.d.ts +10 -0
  19. package/dist/hooks/useStyleEffectHide.d.ts +5 -0
  20. package/dist/hooks/useStyleEffectOffset.d.ts +8 -0
  21. package/dist/hooks/useStyleEffectSwipeBack.d.ts +9 -0
  22. package/dist/hooks/useTheme.d.ts +3 -0
  23. package/dist/index.css +2 -0
  24. package/dist/index.css.map +7 -0
  25. package/dist/index.d.ts +5 -0
  26. package/dist/index.js +2 -0
  27. package/dist/index.js.map +7 -0
  28. package/dist/index.mjs +2 -0
  29. package/dist/index.mjs.map +7 -0
  30. package/dist/styles/f.css.d.ts +18 -0
  31. package/dist/styles/index.d.ts +1 -0
  32. package/dist/theme.css.d.ts +25 -0
  33. package/dist/utils/PropOf.d.ts +2 -0
  34. package/dist/utils/compactMap.d.ts +3 -0
  35. package/dist/utils/index.d.ts +7 -0
  36. package/dist/utils/last.d.ts +1 -0
  37. package/dist/utils/listenOnce.d.ts +1 -0
  38. package/dist/utils/listenResize.d.ts +1 -0
  39. package/dist/utils/noop.d.ts +1 -0
  40. package/dist/utils/requestNextFrame.d.ts +1 -0
  41. package/package.json +61 -0
  42. package/src/assets/IconBack.tsx +21 -0
  43. package/src/assets/IconClose.tsx +25 -0
  44. package/src/assets/index.ts +2 -0
  45. package/src/basicUIPlugin.tsx +48 -0
  46. package/src/components/AppBar.css.ts +173 -0
  47. package/src/components/AppBar.tsx +193 -0
  48. package/src/components/AppScreen.css.ts +159 -0
  49. package/src/components/AppScreen.tsx +106 -0
  50. package/src/components/BottomSheet.css.ts +78 -0
  51. package/src/components/BottomSheet.tsx +91 -0
  52. package/src/components/Modal.css.ts +82 -0
  53. package/src/components/Modal.tsx +91 -0
  54. package/src/hooks/index.ts +7 -0
  55. package/src/hooks/useLazy.tsx +15 -0
  56. package/src/hooks/useMaxWidth.ts +43 -0
  57. package/src/hooks/useStyleEffect.ts +76 -0
  58. package/src/hooks/useStyleEffectHide.ts +34 -0
  59. package/src/hooks/useStyleEffectOffset.ts +57 -0
  60. package/src/hooks/useStyleEffectSwipeBack.ts +228 -0
  61. package/src/hooks/useTheme.ts +9 -0
  62. package/src/index.ts +5 -0
  63. package/src/styles/f.css.ts +84 -0
  64. package/src/styles/index.ts +1 -0
  65. package/src/theme.css.ts +75 -0
  66. package/src/utils/PropOf.ts +1 -0
  67. package/src/utils/compactMap.ts +13 -0
  68. package/src/utils/index.ts +7 -0
  69. package/src/utils/last.ts +1 -0
  70. package/src/utils/listenOnce.ts +12 -0
  71. package/src/utils/listenResize.ts +8 -0
  72. package/src/utils/noop.ts +1 -0
  73. package/src/utils/requestNextFrame.tsx +8 -0
@@ -0,0 +1,48 @@
1
+ import type { StackflowReactPlugin } from "@stackflow/react";
2
+ import { assignInlineVars } from "@vanilla-extract/dynamic";
3
+ import React from "react";
4
+
5
+ import { ThemeProvider } from "./hooks";
6
+ import * as theme from "./theme.css";
7
+ import { compactMap } from "./utils";
8
+
9
+ type RPartial<K> = {
10
+ [attr in keyof K]?: K[attr] extends object ? RPartial<K[attr]> : K[attr];
11
+ };
12
+
13
+ type BasicUIPluginOptions = RPartial<theme.GlobalVars> & {
14
+ theme: "android" | "cupertino";
15
+ };
16
+
17
+ export const basicUIPlugin: (
18
+ options: BasicUIPluginOptions,
19
+ ) => StackflowReactPlugin = (options) => () => ({
20
+ key: "basic-ui",
21
+ wrapStack({ stack }) {
22
+ return (
23
+ <ThemeProvider value={options.theme}>
24
+ <div
25
+ className={theme[options.theme]}
26
+ style={assignInlineVars(
27
+ compactMap({
28
+ [theme.globalVars.backgroundColor]: options.backgroundColor,
29
+ [theme.globalVars.dimBackgroundColor]: options.dimBackgroundColor,
30
+ [theme.globalVars.appBar.borderColor]:
31
+ options.appBar?.borderColor,
32
+ [theme.globalVars.appBar.borderSize]: options.appBar?.borderSize,
33
+ [theme.globalVars.appBar.height]: options.appBar?.height,
34
+ [theme.globalVars.appBar.iconColor]: options.appBar?.iconColor,
35
+ [theme.globalVars.appBar.textColor]: options.appBar?.textColor,
36
+ [theme.globalVars.bottomSheet.borderRadius]:
37
+ options.bottomSheet?.borderRadius,
38
+ [theme.globalVars.modal.borderRadius]:
39
+ options.modal?.borderRadius,
40
+ }),
41
+ )}
42
+ >
43
+ {stack.render()}
44
+ </div>
45
+ </ThemeProvider>
46
+ );
47
+ },
48
+ });
@@ -0,0 +1,173 @@
1
+ import { style } from "@vanilla-extract/css";
2
+ import { calc } from "@vanilla-extract/css-utils";
3
+ import { recipe } from "@vanilla-extract/recipes";
4
+
5
+ import { f } from "../styles";
6
+ import {
7
+ android,
8
+ cupertino,
9
+ globalVars,
10
+ rootAndroid,
11
+ rootCupertino,
12
+ } from "../theme.css";
13
+ import {
14
+ background,
15
+ enterActive,
16
+ enterDone,
17
+ exitActive,
18
+ vars,
19
+ } from "./AppScreen.css";
20
+
21
+ export const appBar = recipe({
22
+ base: [
23
+ f.posAbs,
24
+ f.flexAlignCenter,
25
+ f.fullWidth,
26
+ f.contentBox,
27
+ background,
28
+ {
29
+ height: globalVars.appBar.height,
30
+ paddingTop: ["constant(safe-area-inset-top)", "env(safe-area-inset-top)"],
31
+ zIndex: vars.zIndexes.appBar,
32
+ selectors: {
33
+ [`${cupertino} &, ${rootCupertino} &`]: {
34
+ position: "absolute",
35
+ },
36
+ [`${cupertino} ${exitActive} &, ${rootCupertino} ${exitActive} &`]: {
37
+ transform: "translateX(100%)",
38
+ },
39
+ [`${android} &, ${rootAndroid} &`]: {
40
+ opacity: 0,
41
+ transform: "translateY(10rem)",
42
+ transition: vars.transitionDuration,
43
+ },
44
+ [`${android} ${enterActive} &, ${rootAndroid} ${enterActive} &`]: {
45
+ opacity: 1,
46
+ transform: "translateY(0)",
47
+ },
48
+ [`${android} ${enterDone} &, ${rootAndroid} ${enterDone} &`]: {
49
+ opacity: 1,
50
+ transform: "translateY(0)",
51
+ },
52
+ },
53
+ },
54
+ ],
55
+ variants: {
56
+ border: {
57
+ true: {
58
+ boxShadow: `inset 0px ${calc(
59
+ globalVars.appBar.borderSize,
60
+ ).negate()} 0 ${globalVars.appBar.borderColor}`,
61
+ },
62
+ },
63
+ },
64
+ });
65
+
66
+ export const left = style([
67
+ f.flexAlignCenter,
68
+ f.fullHeight,
69
+ {
70
+ padding: "0 0.5rem",
71
+ ":empty": {
72
+ display: "none",
73
+ },
74
+ },
75
+ ]);
76
+
77
+ export const backButton = style([
78
+ f.flexAlignCenter,
79
+ f.flexJustifyCenter,
80
+ f.cursorPointer,
81
+ f.resetButton,
82
+ {
83
+ color: globalVars.appBar.iconColor,
84
+ transition: "opacity 300ms",
85
+ width: "2.25rem",
86
+ height: "2.75rem",
87
+ ":active": {
88
+ opacity: "0.2",
89
+ transition: "opacity 0s",
90
+ },
91
+ },
92
+ ]);
93
+
94
+ export const closeButton = style([backButton]);
95
+
96
+ export const center = style([
97
+ f.flexAlignCenter,
98
+ {
99
+ flex: 1,
100
+ },
101
+ ]);
102
+
103
+ export const centerMain = recipe({
104
+ base: {
105
+ width: vars.appBar.center.mainWidth,
106
+ color: globalVars.appBar.textColor,
107
+ selectors: {
108
+ [`${android} &, ${rootAndroid} &`]: {
109
+ width: "100%",
110
+ justifyContent: "flex-start",
111
+ paddingLeft: "1rem",
112
+ fontSize: "1.1875rem",
113
+ lineHeight: "1.5",
114
+ fontWeight: "bold",
115
+ boxSizing: "border-box",
116
+ },
117
+ [`${cupertino} &, ${rootCupertino} &`]: {
118
+ position: "absolute",
119
+ display: "flex",
120
+ alignItems: "center",
121
+ justifyContent: "center",
122
+ textAlign: "center",
123
+ fontFamily: "-apple-system, BlinkMacSystemFont",
124
+ fontWeight: 600,
125
+ fontSize: "1rem",
126
+ left: "50%",
127
+ transform: "translate(-50%)",
128
+ height: globalVars.appBar.height,
129
+ top: ["constant(safe-area-inset-top)", "env(safe-area-inset-top)"],
130
+ },
131
+ },
132
+ },
133
+ variants: {
134
+ hasLeft: {
135
+ true: {
136
+ selectors: {
137
+ [`${android} &, ${rootAndroid} &`]: {
138
+ paddingLeft: "0.375rem",
139
+ },
140
+ },
141
+ },
142
+ },
143
+ },
144
+ });
145
+
146
+ export const centerText = style([
147
+ f.overflowHidden,
148
+ f.whiteSpaceNowrap,
149
+ f.fullWidth,
150
+ {
151
+ textOverflow: "ellipsis",
152
+ fontSize: "inherit",
153
+ fontWeight: "inherit",
154
+ },
155
+ ]);
156
+
157
+ export const right = style([
158
+ f.flexAlignCenter,
159
+ f.fullHeight,
160
+ f.posRel,
161
+ {
162
+ padding: "0 0.5rem",
163
+ marginLeft: "auto",
164
+ ":empty": {
165
+ display: "none",
166
+ },
167
+ selectors: {
168
+ [`${android} &, ${rootAndroid} &`]: {
169
+ padding: "0 0.5rem 0 0",
170
+ },
171
+ },
172
+ },
173
+ ]);
@@ -0,0 +1,193 @@
1
+ import { useActions, useActivity } from "@stackflow/react";
2
+ import { assignInlineVars } from "@vanilla-extract/dynamic";
3
+ import React, { useRef } from "react";
4
+
5
+ import { IconBack, IconClose } from "../assets";
6
+ import { useMaxWidth, useTheme } from "../hooks";
7
+ import type { GlobalVars } from "../theme.css";
8
+ import { globalVars } from "../theme.css";
9
+ import { compactMap, noop } from "../utils";
10
+ import * as css from "./AppBar.css";
11
+ import * as appScreenCss from "./AppScreen.css";
12
+
13
+ type AppBarProps = Partial<
14
+ Pick<
15
+ GlobalVars["appBar"],
16
+ "borderColor" | "borderSize" | "height" | "iconColor" | "textColor"
17
+ >
18
+ > & {
19
+ title?: React.ReactNode;
20
+ appendLeft?: () => React.ReactNode;
21
+ appendRight?: () => React.ReactNode;
22
+ backButton?:
23
+ | {
24
+ renderIcon?: () => React.ReactNode;
25
+ onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
26
+ }
27
+ | {
28
+ render?: () => React.ReactNode;
29
+ };
30
+ closeButton?:
31
+ | {
32
+ renderIcon?: () => React.ReactNode;
33
+ onClick: (e: React.MouseEvent<HTMLButtonElement>) => void;
34
+ }
35
+ | {
36
+ render?: () => React.ReactNode;
37
+ };
38
+ closeButtonLocation?: "left" | "right";
39
+ border?: boolean;
40
+ };
41
+ const AppBar = React.forwardRef<HTMLDivElement, AppBarProps>(
42
+ (
43
+ {
44
+ title,
45
+ appendLeft,
46
+ appendRight,
47
+ backButton,
48
+ closeButton,
49
+ closeButtonLocation = "left",
50
+ border = true,
51
+ iconColor,
52
+ textColor,
53
+ borderColor,
54
+ borderSize,
55
+ height,
56
+ },
57
+ ref,
58
+ ) => {
59
+ const actions = useActions();
60
+ const activity = useActivity();
61
+
62
+ const theme = useTheme();
63
+
64
+ const centerRef = useRef<any>(null);
65
+
66
+ const { maxWidth } = useMaxWidth({
67
+ outerRef: ref,
68
+ innerRef: centerRef,
69
+ enable: theme === "cupertino",
70
+ });
71
+
72
+ const onBackClick = (e: React.MouseEvent<HTMLButtonElement>) => {
73
+ if (backButton && "onClick" in backButton && backButton.onClick) {
74
+ backButton.onClick(e);
75
+ }
76
+
77
+ if (!e.defaultPrevented) {
78
+ actions.pop();
79
+ }
80
+ };
81
+
82
+ const isCloseButtonVisible =
83
+ activity.zIndex === 0 ||
84
+ (activity.zIndex === 1 &&
85
+ activity.transitionState === "enter-active" &&
86
+ activity.pushedBy.name === "Replaced");
87
+
88
+ const renderBackButton = () => {
89
+ if (isCloseButtonVisible) {
90
+ return null;
91
+ }
92
+
93
+ if (!backButton) {
94
+ return (
95
+ <button
96
+ type="button"
97
+ className={css.backButton}
98
+ onClick={onBackClick}
99
+ >
100
+ <IconBack />
101
+ </button>
102
+ );
103
+ }
104
+
105
+ if ("render" in backButton && backButton.render) {
106
+ return backButton.render?.();
107
+ }
108
+
109
+ return (
110
+ <button type="button" className={css.backButton} onClick={onBackClick}>
111
+ {"renderIcon" in backButton && backButton.renderIcon ? (
112
+ backButton.renderIcon()
113
+ ) : (
114
+ <IconBack />
115
+ )}
116
+ </button>
117
+ );
118
+ };
119
+
120
+ const renderCloseButton = () => {
121
+ if (!closeButton || !isCloseButtonVisible) {
122
+ return null;
123
+ }
124
+ if ("render" in closeButton && closeButton.render) {
125
+ return closeButton.render();
126
+ }
127
+
128
+ return (
129
+ <button
130
+ type="button"
131
+ className={css.closeButton}
132
+ onClick={"onClick" in closeButton ? closeButton.onClick : noop}
133
+ >
134
+ {"renderIcon" in closeButton && closeButton.renderIcon ? (
135
+ closeButton.renderIcon()
136
+ ) : (
137
+ <IconClose />
138
+ )}
139
+ </button>
140
+ );
141
+ };
142
+
143
+ const hasLeft = !!(
144
+ (closeButtonLocation === "left" && closeButton) ||
145
+ backButton ||
146
+ appendLeft
147
+ );
148
+
149
+ return (
150
+ <div
151
+ ref={ref}
152
+ className={css.appBar({
153
+ border,
154
+ })}
155
+ style={assignInlineVars(
156
+ compactMap({
157
+ [globalVars.appBar.iconColor]: iconColor,
158
+ [globalVars.appBar.textColor]: textColor,
159
+ [globalVars.appBar.borderColor]: borderColor,
160
+ [globalVars.appBar.borderSize]: borderSize,
161
+ [globalVars.appBar.height]: height,
162
+ [appScreenCss.vars.appBar.center.mainWidth]: `${maxWidth}px`,
163
+ }),
164
+ )}
165
+ >
166
+ <div className={css.left}>
167
+ {closeButtonLocation === "left" && renderCloseButton()}
168
+ {renderBackButton()}
169
+ {appendLeft?.()}
170
+ </div>
171
+ <div ref={centerRef} className={css.center}>
172
+ <div
173
+ className={css.centerMain({
174
+ hasLeft,
175
+ })}
176
+ >
177
+ {typeof title === "string" ? (
178
+ <div className={css.centerText}>{title}</div>
179
+ ) : (
180
+ title
181
+ )}
182
+ </div>
183
+ </div>
184
+ <div className={css.right}>
185
+ {appendRight?.()}
186
+ {closeButtonLocation === "right" && renderCloseButton()}
187
+ </div>
188
+ </div>
189
+ );
190
+ },
191
+ );
192
+
193
+ export default AppBar;
@@ -0,0 +1,159 @@
1
+ import { createThemeContract, style } from "@vanilla-extract/css";
2
+ import { calc } from "@vanilla-extract/css-utils";
3
+ import { recipe } from "@vanilla-extract/recipes";
4
+
5
+ import { f } from "../styles";
6
+ import {
7
+ android,
8
+ cupertino,
9
+ globalVars,
10
+ rootAndroid,
11
+ rootCupertino,
12
+ } from "../theme.css";
13
+
14
+ export const vars = createThemeContract({
15
+ transitionDuration: null,
16
+ zIndexes: {
17
+ dim: null,
18
+ paper: null,
19
+ edge: null,
20
+ appBar: null,
21
+ },
22
+ appBar: {
23
+ center: {
24
+ mainWidth: null,
25
+ },
26
+ },
27
+ });
28
+
29
+ const dimBackgroundColor = style({
30
+ backgroundColor: globalVars.dimBackgroundColor,
31
+ });
32
+
33
+ export const background = style({
34
+ backgroundColor: globalVars.backgroundColor,
35
+ });
36
+
37
+ export const allTransitions = style({
38
+ transition: vars.transitionDuration,
39
+ });
40
+
41
+ export const enterActive = style({});
42
+ export const enterDone = style({});
43
+ export const exitActive = style({});
44
+ export const exitDone = style({
45
+ transform: "translateX(100%)",
46
+ });
47
+
48
+ export const appScreen = recipe({
49
+ base: [f.posAbsFull, f.overflowHidden],
50
+ variants: {
51
+ transitionState: {
52
+ "enter-active": enterActive,
53
+ "enter-done": enterDone,
54
+ "exit-active": exitActive,
55
+ "exit-done": exitDone,
56
+ },
57
+ },
58
+ });
59
+
60
+ export const dim = style([
61
+ f.posAbsFull,
62
+ dimBackgroundColor,
63
+ allTransitions,
64
+ {
65
+ opacity: 0,
66
+ zIndex: vars.zIndexes.dim,
67
+ selectors: {
68
+ [`${android} &, ${rootAndroid} &`]: {
69
+ height: "10rem",
70
+ background: `linear-gradient(${globalVars.dimBackgroundColor}, rgba(0, 0, 0, 0))`,
71
+ },
72
+ [`${enterActive} &`]: {
73
+ opacity: 1,
74
+ },
75
+ [`${enterDone} &`]: {
76
+ opacity: 1,
77
+ },
78
+ [`${exitActive} &`]: {
79
+ opacity: 0,
80
+ },
81
+ [`${exitDone} &`]: {
82
+ opacity: 0,
83
+ },
84
+ },
85
+ },
86
+ ]);
87
+
88
+ export const paper = recipe({
89
+ base: [
90
+ f.posAbsFull,
91
+ background,
92
+ allTransitions,
93
+ {
94
+ overflowY: "scroll",
95
+ WebkitOverflowScrolling: "touch",
96
+ "::-webkit-scrollbar": {
97
+ display: "none",
98
+ },
99
+ zIndex: vars.zIndexes.paper,
100
+ selectors: {
101
+ [`${cupertino} &, ${rootCupertino} &`]: {
102
+ transform: "translateX(100%)",
103
+ },
104
+ [`${cupertino} ${enterActive} &, ${rootCupertino} ${enterActive} &`]: {
105
+ transform: "translateX(0)",
106
+ },
107
+ [`${cupertino} ${enterDone} &, ${rootCupertino} ${enterDone} &`]: {
108
+ transform: "translateX(0)",
109
+ },
110
+ [`${android} &, ${rootAndroid} &`]: {
111
+ opacity: 0,
112
+ transform: "translateY(10rem)",
113
+ },
114
+ [`${android} ${enterActive} &, ${rootAndroid} ${enterActive} &`]: {
115
+ opacity: 1,
116
+ transform: "translateY(0)",
117
+ },
118
+ [`${android} ${enterDone} &, ${rootAndroid} ${enterDone} &`]: {
119
+ opacity: 1,
120
+ transform: "translateY(0)",
121
+ },
122
+ },
123
+ },
124
+ ],
125
+ variants: {
126
+ hasAppBar: {
127
+ true: [
128
+ f.borderBox,
129
+ {
130
+ paddingTop: [
131
+ `calc(${globalVars.appBar.height} + constant(safe-area-inset-top))`,
132
+ `calc(${globalVars.appBar.height} + env(safe-area-inset-top))`,
133
+ ],
134
+ },
135
+ ],
136
+ },
137
+ },
138
+ });
139
+
140
+ export const edge = recipe({
141
+ base: [
142
+ f.posAbs,
143
+ f.top0,
144
+ f.left0,
145
+ f.fullHeight,
146
+ {
147
+ width: "1.25rem",
148
+ zIndex: vars.zIndexes.edge,
149
+ },
150
+ ],
151
+ variants: {
152
+ hasAppBar: {
153
+ true: {
154
+ top: globalVars.appBar.height,
155
+ height: calc("100%").subtract(globalVars.appBar.height).toString(),
156
+ },
157
+ },
158
+ },
159
+ });
@@ -0,0 +1,106 @@
1
+ /* eslint-disable no-param-reassign */
2
+
3
+ import { useActions, useActivity } from "@stackflow/react";
4
+ import { assignInlineVars } from "@vanilla-extract/dynamic";
5
+ import React, { useRef } from "react";
6
+
7
+ import {
8
+ useLazy,
9
+ useStyleEffectHide,
10
+ useStyleEffectOffset,
11
+ useStyleEffectSwipeBack,
12
+ useTheme,
13
+ } from "../hooks";
14
+ import type { GlobalVars } from "../theme.css";
15
+ import { globalVars } from "../theme.css";
16
+ import type { PropOf } from "../utils";
17
+ import { compactMap } from "../utils";
18
+ import AppBar from "./AppBar";
19
+ import * as css from "./AppScreen.css";
20
+
21
+ type AppScreenProps = Partial<
22
+ Pick<GlobalVars, "backgroundColor" | "dimBackgroundColor">
23
+ > & {
24
+ appBar?: Omit<PropOf<typeof AppBar>, "theme" | "ref" | "key">;
25
+ children: React.ReactNode;
26
+ };
27
+ const AppScreen: React.FC<AppScreenProps> = ({ appBar, children }) => {
28
+ const theme = useTheme();
29
+ const activity = useActivity();
30
+ const { pop } = useActions();
31
+
32
+ const appScreenRef = useRef<HTMLDivElement>(null);
33
+ const dimRef = useRef<HTMLDivElement>(null);
34
+ const paperRef = useRef<HTMLDivElement>(null);
35
+ const edgeRef = useRef<HTMLDivElement>(null);
36
+ const appBarRef = useRef<HTMLDivElement>(null);
37
+
38
+ useStyleEffectHide({
39
+ refs: [appScreenRef],
40
+ hasEffect: true,
41
+ });
42
+ useStyleEffectOffset({
43
+ theme,
44
+ refs: theme === "cupertino" ? [paperRef] : [paperRef, appBarRef],
45
+ hasEffect: true,
46
+ });
47
+ useStyleEffectSwipeBack({
48
+ theme,
49
+ dimRef,
50
+ edgeRef,
51
+ paperRef,
52
+ hasEffect: true,
53
+ onSwiped() {
54
+ pop();
55
+ },
56
+ });
57
+
58
+ const isRoot = activity.zIndex === 0;
59
+ const hasAppBar = !!appBar;
60
+
61
+ const zIndexBase = activity.zIndex * 5;
62
+ const zIndexDim = zIndexBase;
63
+ const zIndexPaper = zIndexBase + (theme === "cupertino" && hasAppBar ? 1 : 3);
64
+ const zIndexEdge = zIndexBase + 4;
65
+ const zIndexAppBar = zIndexBase + 7;
66
+
67
+ return (
68
+ <div
69
+ ref={appScreenRef}
70
+ className={css.appScreen({
71
+ transitionState: useLazy(activity.transitionState),
72
+ })}
73
+ style={assignInlineVars(
74
+ compactMap({
75
+ [globalVars.appBar.height]: appBar?.height,
76
+ [css.vars.zIndexes.dim]: `${zIndexDim}`,
77
+ [css.vars.zIndexes.paper]: `${zIndexPaper}`,
78
+ [css.vars.zIndexes.edge]: `${zIndexEdge}`,
79
+ [css.vars.zIndexes.appBar]: `${zIndexAppBar}`,
80
+ [css.vars.transitionDuration]:
81
+ activity.transitionState === "enter-active" ||
82
+ activity.transitionState === "exit-active"
83
+ ? `var(--stackflow-transition-duration)`
84
+ : "0ms",
85
+ }),
86
+ )}
87
+ >
88
+ <div className={css.dim} ref={dimRef} />
89
+ <div
90
+ key={activity.id}
91
+ className={css.paper({
92
+ hasAppBar,
93
+ })}
94
+ ref={paperRef}
95
+ >
96
+ {children}
97
+ </div>
98
+ {!isRoot && theme === "cupertino" && (
99
+ <div className={css.edge({ hasAppBar })} ref={edgeRef} />
100
+ )}
101
+ {appBar && <AppBar {...appBar} ref={appBarRef} />}
102
+ </div>
103
+ );
104
+ };
105
+
106
+ export default AppScreen;