@sincpro/mobile-ui 3.1.0 → 3.2.0

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.
@@ -2,7 +2,7 @@ import { c as _c } from "react/compiler-runtime";
2
2
  import { FlashList } from "@shopify/flash-list";
3
3
  import Sheet from "./Dialog.Sheet.js";
4
4
  import { DialogActions } from "./dialog-actions.js";
5
- import Pressable from "../primitives/Pressable.js";
5
+ import { ChoiceRow } from "../Form/choice-row.js";
6
6
  import { fontFamilies, useTheme } from "../theme/index.js";
7
7
  import { Typography } from "../Typography/index.js";
8
8
  import { attempt, errorMessage } from "../utils/async.js";
@@ -245,29 +245,16 @@ function EditValueEditor(t0) {
245
245
  const {
246
246
  item
247
247
  } = t24;
248
- return _jsx(Pressable, {
249
- accessibilityLabel: item.label,
250
- accessibilityRole: "radio",
251
- accessibilityState: {
252
- disabled: blocked || !!item.disabled,
253
- selected: item.value === draft
254
- },
255
- className: "border-b border-border-light py-3",
256
- disabled: blocked || item.disabled,
248
+ return _jsx(ChoiceRow, {
249
+ disabled: blocked || !!item.disabled,
250
+ label: item.label,
251
+ look: "list",
257
252
  onPress: () => {
258
253
  if (!item.disabled) {
259
254
  updateDraft(item.value);
260
255
  }
261
256
  },
262
- style: {
263
- minWidth: 48,
264
- minHeight: 48
265
- },
266
- children: _jsx(Typography.Text, {
267
- className: item.disabled ? "text-text-disabled" : "text-text-primary",
268
- semibold: item.value === draft,
269
- children: item.label
270
- })
257
+ selected: item.value === draft
271
258
  });
272
259
  };
273
260
  $[40] = blocked;
@@ -1,11 +1,57 @@
1
1
  import { c as _c } from "react/compiler-runtime";
2
2
  import { OverlayPortal } from "./OverlayHost.js";
3
- import { SheetSurface } from "./SheetSurface.js";
3
+ import { SheetSurface, useSheetRestingOffset } from "./SheetSurface.js";
4
4
  import Pressable from "../primitives/Pressable.js";
5
5
  import { Typography } from "../Typography/index.js";
6
6
  import { useState } from "react";
7
7
  import { ScrollView, View } from "react-native";
8
8
  import { jsx as _jsx, jsxs as _jsxs } from "nativewind/jsx-runtime";
9
+ /** Scroll content gets the hidden part of a resting panel as room at its end. */
10
+ function SheetScroll(t0) {
11
+ const $ = _c(6);
12
+ const {
13
+ children
14
+ } = t0;
15
+ const restingOffset = useSheetRestingOffset();
16
+ const t1 = 16 + restingOffset;
17
+ let t2;
18
+ if ($[0] !== t1) {
19
+ t2 = {
20
+ paddingHorizontal: 16,
21
+ paddingBottom: t1
22
+ };
23
+ $[0] = t1;
24
+ $[1] = t2;
25
+ } else {
26
+ t2 = $[1];
27
+ }
28
+ let t3;
29
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
30
+ t3 = {
31
+ flex: 1,
32
+ minHeight: 0
33
+ };
34
+ $[2] = t3;
35
+ } else {
36
+ t3 = $[2];
37
+ }
38
+ let t4;
39
+ if ($[3] !== children || $[4] !== t2) {
40
+ t4 = _jsx(ScrollView, {
41
+ contentContainerStyle: t2,
42
+ keyboardDismissMode: "on-drag",
43
+ keyboardShouldPersistTaps: "handled",
44
+ style: t3,
45
+ children: children
46
+ });
47
+ $[3] = children;
48
+ $[4] = t2;
49
+ $[5] = t4;
50
+ } else {
51
+ t4 = $[5];
52
+ }
53
+ return t4;
54
+ }
9
55
  const SNAP_POINTS = ["60%", "90%"];
10
56
  function Sheet(t0) {
11
57
  const $ = _c(41);
@@ -169,17 +215,7 @@ function Sheet(t0) {
169
215
  }
170
216
  let t18;
171
217
  if ($[25] !== children || $[26] !== scrollable) {
172
- t18 = scrollable ? _jsx(ScrollView, {
173
- contentContainerStyle: {
174
- paddingHorizontal: 16,
175
- paddingBottom: 16
176
- },
177
- keyboardDismissMode: "on-drag",
178
- keyboardShouldPersistTaps: "handled",
179
- style: {
180
- flex: 1,
181
- minHeight: 0
182
- },
218
+ t18 = scrollable ? _jsx(SheetScroll, {
183
219
  children: children
184
220
  }) : _jsx(View, {
185
221
  style: {
@@ -15,7 +15,8 @@ export interface OverlayPortalProps {
15
15
  }
16
16
  /**
17
17
  * Sends its children to the OverlayHost. Without a host (tests, isolated
18
- * stories) it renders in place so the content stays reachable.
18
+ * stories) it renders in place so the content stays reachable, and warns once in
19
+ * development, because an app without the host draws every overlay clipped.
19
20
  *
20
21
  * Content rendered in the host sees the providers above the host, not the
21
22
  * screen-level providers around the portal. Pass what it needs as props.
@@ -122,15 +122,25 @@ function _temp2(entry_0) {
122
122
  function _temp(entry) {
123
123
  return entry.layer === "sheet";
124
124
  }
125
+ let warnedMissingHost = false;
126
+
127
+ /** Overlays without a host render in place, clipped by their container: say so once. */
128
+ function warnMissingHost() {
129
+ if (warnedMissingHost || !__DEV__ || process.env.NODE_ENV === "test") return;
130
+ warnedMissingHost = true;
131
+ console.warn("[mobile-ui] A Sheet or dialog opened without <OverlayHost>: it renders in place, " + "clipped by its container. Mount <OverlayHost> once at the app root " + "(the @sincpro/mobile AppShell does it).");
132
+ }
133
+
125
134
  /**
126
135
  * Sends its children to the OverlayHost. Without a host (tests, isolated
127
- * stories) it renders in place so the content stays reachable.
136
+ * stories) it renders in place so the content stays reachable, and warns once in
137
+ * development, because an app without the host draws every overlay clipped.
128
138
  *
129
139
  * Content rendered in the host sees the providers above the host, not the
130
140
  * screen-level providers around the portal. Pass what it needs as props.
131
141
  */
132
142
  export function OverlayPortal(t0) {
133
- const $ = _c(13);
143
+ const $ = _c(16);
134
144
  const {
135
145
  children,
136
146
  layer: t1,
@@ -192,5 +202,29 @@ export function OverlayPortal(t0) {
192
202
  t5 = $[12];
193
203
  }
194
204
  useLayoutEffect(t4, t5);
205
+ let t6;
206
+ let t7;
207
+ if ($[13] !== hosted) {
208
+ t6 = () => {
209
+ if (hosted) {
210
+ return;
211
+ }
212
+ const timer = setTimeout(_temp6, 0);
213
+ return () => clearTimeout(timer);
214
+ };
215
+ t7 = [hosted];
216
+ $[13] = hosted;
217
+ $[14] = t6;
218
+ $[15] = t7;
219
+ } else {
220
+ t6 = $[14];
221
+ t7 = $[15];
222
+ }
223
+ useEffect(t6, t7);
195
224
  return hosted ? null : children;
196
225
  }
226
+ function _temp6() {
227
+ if (!overlayStore.hasHost()) {
228
+ warnMissingHost();
229
+ }
230
+ }
@@ -1,6 +1,25 @@
1
1
  import { type ReactNode } from "react";
2
2
  export type SnapPoint = string | number;
3
+ /** The part of the sheet panel below the screen at rest (0 outside a sheet). */
4
+ export declare function useSheetRestingOffset(): number;
3
5
  export declare function resolveSnapPoint(point: SnapPoint, windowHeight: number): number;
6
+ /**
7
+ * Panel geometry for a host of `height` whose top `topInset` points are covered (status
8
+ * bar, notch). The panel is as tall as the highest snap point and never reaches into the
9
+ * inset; it rests pushed down `restOffset` so only the lowest snap point shows.
10
+ */
11
+ export declare function sheetGeometry(snapPoints: SnapPoint[], height: number, topInset: number): {
12
+ ceiling: number;
13
+ panelHeight: number;
14
+ offsets: number[];
15
+ restOffset: number;
16
+ };
17
+ /**
18
+ * How much of the panel sits below the screen while it rests at its lowest snap point.
19
+ * Scroll content needs this much extra room at its end, or its last rows stay off screen
20
+ * until the sheet is dragged up.
21
+ */
22
+ export declare function restingOffset(snapPoints: SnapPoint[], height: number, topInset: number): number;
4
23
  export interface SheetSurfaceProps {
5
24
  /** `false` starts the exit animation. */
6
25
  visible: boolean;