@stackflow/plugin-basic-ui 0.21.0 → 0.21.2

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.
@@ -7,7 +7,7 @@ import { useGlobalOptions } from "../basicUIPlugin";
7
7
  import { useMaxWidth, useNullableActivity } from "../hooks";
8
8
  import type { GlobalVars } from "../theme.css";
9
9
  import { globalVars } from "../theme.css";
10
- import { compactMap, noop } from "../utils";
10
+ import { compactMap } from "../utils";
11
11
  import * as css from "./AppBar.css";
12
12
  import * as appScreenCss from "./AppScreen.css";
13
13
 
@@ -46,6 +46,7 @@ type AppBarProps = Partial<
46
46
  };
47
47
  closeButtonLocation?: "left" | "right";
48
48
  border?: boolean;
49
+ modalPresentationStyle?: "fullScreen";
49
50
  onTopClick?: (e: React.MouseEvent) => void;
50
51
  };
51
52
  const AppBar = React.forwardRef<HTMLDivElement, AppBarProps>(
@@ -58,6 +59,7 @@ const AppBar = React.forwardRef<HTMLDivElement, AppBarProps>(
58
59
  closeButton,
59
60
  closeButtonLocation = "left",
60
61
  border = true,
62
+ modalPresentationStyle,
61
63
  iconColor,
62
64
  textColor,
63
65
  borderColor,
@@ -83,6 +85,8 @@ const AppBar = React.forwardRef<HTMLDivElement, AppBarProps>(
83
85
  enable: globalOptions.theme === "cupertino",
84
86
  });
85
87
 
88
+ const presentModalFullScreen = modalPresentationStyle === "fullScreen";
89
+
86
90
  const onBackClick = (e: React.MouseEvent<HTMLButtonElement>) => {
87
91
  if (backButton && "onClick" in backButton && backButton.onClick) {
88
92
  backButton.onClick(e);
@@ -153,6 +157,10 @@ const AppBar = React.forwardRef<HTMLDivElement, AppBarProps>(
153
157
  return globalBackButton.renderIcon();
154
158
  }
155
159
 
160
+ if (presentModalFullScreen) {
161
+ return <IconClose />;
162
+ }
163
+
156
164
  return <IconBack />;
157
165
  })()}
158
166
  </button>
@@ -176,7 +184,20 @@ const AppBar = React.forwardRef<HTMLDivElement, AppBarProps>(
176
184
  const renderCloseButton = () => {
177
185
  const isRoot = !activity || activity.isRoot;
178
186
 
179
- if ((!closeButton && !globalOptions.appBar?.closeButton) || !isRoot) {
187
+ const showCloseButton = (closeButton: AppBarProps["closeButton"]) =>
188
+ (closeButton && "render" in closeButton && closeButton.render) ||
189
+ (closeButton &&
190
+ "renderIcon" in closeButton &&
191
+ closeButton.renderIcon) ||
192
+ (closeButton && "onClick" in closeButton && closeButton.onClick);
193
+
194
+ if (
195
+ !(
196
+ showCloseButton(closeButton) ||
197
+ showCloseButton(globalOptions.appBar?.closeButton)
198
+ ) ||
199
+ !isRoot
200
+ ) {
180
201
  return null;
181
202
  }
182
203
  if (closeButton && "render" in closeButton && closeButton.render) {
@@ -236,6 +257,7 @@ const AppBar = React.forwardRef<HTMLDivElement, AppBarProps>(
236
257
  ref={ref}
237
258
  className={css.appBar({
238
259
  border,
260
+ presentModalFullScreen,
239
261
  })}
240
262
  style={assignInlineVars(
241
263
  compactMap({
@@ -65,20 +65,23 @@ export const dim = style([
65
65
  zIndex: vars.zIndexes.dim,
66
66
  willChange: "opacity",
67
67
  selectors: {
68
- [`${android} &, ${rootAndroid} &`]: {
68
+ [`
69
+ ${android} &,
70
+ ${rootAndroid} &
71
+ `]: {
69
72
  height: "10rem",
70
73
  background: `linear-gradient(${globalVars.dimBackgroundColor}, rgba(0, 0, 0, 0))`,
71
74
  },
72
- [`${enterActive} &`]: {
75
+ [`
76
+ ${enterActive} &,
77
+ ${enterDone} &
78
+ `]: {
73
79
  opacity: 1,
74
80
  },
75
- [`${enterDone} &`]: {
76
- opacity: 1,
77
- },
78
- [`${exitActive} &`]: {
79
- opacity: 0,
80
- },
81
- [`${exitDone} &`]: {
81
+ [`
82
+ ${exitActive} &,
83
+ ${exitDone} &
84
+ `]: {
82
85
  opacity: 0,
83
86
  },
84
87
  },
@@ -99,24 +102,33 @@ export const paper = recipe({
99
102
  zIndex: vars.zIndexes.paper,
100
103
  willChange: "transform",
101
104
  selectors: {
102
- [`${cupertino} &, ${rootCupertino} &`]: {
105
+ [`
106
+ ${cupertino} &,
107
+ ${rootCupertino} &
108
+ `]: {
103
109
  transform: "translate3d(100%, 0, 0)",
104
110
  },
105
- [`${cupertino} ${enterActive} &, ${rootCupertino} ${enterActive} &`]: {
111
+ [`
112
+ ${cupertino} ${enterActive} &,
113
+ ${rootCupertino} ${enterActive} &,
114
+ ${cupertino} ${enterDone} &,
115
+ ${rootCupertino} ${enterDone} &
116
+ `]: {
106
117
  transform: "translate3d(0, 0, 0)",
107
118
  },
108
- [`${cupertino} ${enterDone} &, ${rootCupertino} ${enterDone} &`]: {
109
- transform: "translate3d(0, 0, 0)",
110
- },
111
- [`${android} &, ${rootAndroid} &`]: {
119
+ [`
120
+ ${android} &,
121
+ ${rootAndroid} &
122
+ `]: {
112
123
  opacity: 0,
113
124
  transform: "translate3d(0, 10rem, 0)",
114
125
  },
115
- [`${android} ${enterActive} &, ${rootAndroid} ${enterActive} &`]: {
116
- opacity: 1,
117
- transform: "translate3d(0, 0, 0)",
118
- },
119
- [`${android} ${enterDone} &, ${rootAndroid} ${enterDone} &`]: {
126
+ [`
127
+ ${android} ${enterActive} &,
128
+ ${rootAndroid} ${enterActive} &,
129
+ ${android} ${enterDone} &,
130
+ ${rootAndroid} ${enterDone} &
131
+ `]: {
120
132
  opacity: 1,
121
133
  transform: "translate3d(0, 0, 0)",
122
134
  },
@@ -136,6 +148,18 @@ export const paper = recipe({
136
148
  },
137
149
  ],
138
150
  },
151
+ presentModalFullScreen: {
152
+ true: {
153
+ selectors: {
154
+ [`
155
+ ${cupertino} &,
156
+ ${rootCupertino} &
157
+ `]: {
158
+ transform: "translate3d(0, 100%, 0)",
159
+ },
160
+ },
161
+ },
162
+ },
139
163
  },
140
164
  });
141
165
 
@@ -33,6 +33,7 @@ export type AppScreenProps = Partial<
33
33
  > & {
34
34
  appBar?: Omit<PropOf<typeof AppBar>, "theme" | "ref" | "key">;
35
35
  preventSwipeBack?: boolean;
36
+ modalPresentationStyle?: "fullScreen";
36
37
  children: React.ReactNode;
37
38
  };
38
39
  const AppScreen: React.FC<AppScreenProps> = ({
@@ -40,10 +41,12 @@ const AppScreen: React.FC<AppScreenProps> = ({
40
41
  dimBackgroundColor,
41
42
  appBar,
42
43
  preventSwipeBack,
44
+ modalPresentationStyle,
43
45
  children,
44
46
  }) => {
45
47
  const globalOptions = useGlobalOptions();
46
48
  const activity = useNullableActivity();
49
+
47
50
  const { pop } = useActions();
48
51
 
49
52
  const appScreenRef = useRef<HTMLDivElement>(null);
@@ -52,6 +55,9 @@ const AppScreen: React.FC<AppScreenProps> = ({
52
55
  const edgeRef = useRef<HTMLDivElement>(null);
53
56
  const appBarRef = useRef<HTMLDivElement>(null);
54
57
 
58
+ const presentModalFullScreen = modalPresentationStyle === "fullScreen";
59
+ const swipeBackPrevented = preventSwipeBack || presentModalFullScreen;
60
+
55
61
  useStyleEffectHide({
56
62
  refs: [appScreenRef],
57
63
  hasEffect: true,
@@ -60,7 +66,7 @@ const AppScreen: React.FC<AppScreenProps> = ({
60
66
  theme: globalOptions.theme,
61
67
  refs:
62
68
  globalOptions.theme === "cupertino" ? [paperRef] : [paperRef, appBarRef],
63
- hasEffect: true,
69
+ hasEffect: !presentModalFullScreen,
64
70
  });
65
71
  useStyleEffectSwipeBack({
66
72
  theme: globalOptions.theme,
@@ -68,6 +74,7 @@ const AppScreen: React.FC<AppScreenProps> = ({
68
74
  edgeRef,
69
75
  paperRef,
70
76
  hasEffect: true,
77
+ prevented: swipeBackPrevented,
71
78
  onSwiped() {
72
79
  pop();
73
80
  },
@@ -139,12 +146,18 @@ const AppScreen: React.FC<AppScreenProps> = ({
139
146
  >
140
147
  <div className={css.dim} ref={dimRef} />
141
148
  {appBar && (
142
- <AppBar {...appBar} ref={appBarRef} onTopClick={onAppBarTopClick} />
149
+ <AppBar
150
+ {...appBar}
151
+ ref={appBarRef}
152
+ modalPresentationStyle={modalPresentationStyle}
153
+ onTopClick={onAppBarTopClick}
154
+ />
143
155
  )}
144
156
  <div
145
157
  key={activity?.id}
146
158
  className={css.paper({
147
159
  hasAppBar,
160
+ presentModalFullScreen,
148
161
  })}
149
162
  ref={paperRef}
150
163
  >
@@ -152,7 +165,7 @@ const AppScreen: React.FC<AppScreenProps> = ({
152
165
  </div>
153
166
  {!activity?.isRoot &&
154
167
  globalOptions.theme === "cupertino" &&
155
- !preventSwipeBack && (
168
+ !swipeBackPrevented && (
156
169
  <div className={css.edge({ hasAppBar })} ref={edgeRef} />
157
170
  )}
158
171
  </div>
@@ -18,6 +18,7 @@ export function useStyleEffect({
18
18
  styleName,
19
19
  refs,
20
20
  effect,
21
+ effectDeps,
21
22
  }: {
22
23
  styleName: string;
23
24
  refs: Array<React.RefObject<any>>;
@@ -25,6 +26,7 @@ export function useStyleEffect({
25
26
  activityTransitionState: ActivityTransitionState;
26
27
  refs: Array<React.RefObject<HTMLElement>>;
27
28
  }) => (() => void) | void;
29
+ effectDeps?: any[];
28
30
  }) {
29
31
  const activity = useNullableActivity();
30
32
 
@@ -79,5 +81,5 @@ export function useStyleEffect({
79
81
  return () => {
80
82
  cleanup?.();
81
83
  };
82
- }, [activity?.transitionState]);
84
+ }, [activity?.transitionState, ...(effectDeps ?? [])]);
83
85
  }
@@ -10,6 +10,7 @@ export function useStyleEffectSwipeBack({
10
10
  edgeRef,
11
11
  paperRef,
12
12
  hasEffect,
13
+ prevented,
13
14
  onSwiped,
14
15
  }: {
15
16
  theme: "android" | "cupertino";
@@ -17,6 +18,7 @@ export function useStyleEffectSwipeBack({
17
18
  edgeRef: React.RefObject<HTMLDivElement>;
18
19
  paperRef: React.RefObject<HTMLDivElement>;
19
20
  hasEffect?: boolean;
21
+ prevented?: boolean;
20
22
  onSwiped?: () => void;
21
23
  }) {
22
24
  useStyleEffect({
@@ -236,5 +238,6 @@ export function useStyleEffectSwipeBack({
236
238
  };
237
239
  }
238
240
  : undefined,
241
+ effectDeps: [prevented],
239
242
  });
240
243
  }