@buoy-gg/bottom-sheet 7.0.15 → 7.0.17

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.
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Platform-free geometry for the BottomSheet.
5
+ *
6
+ * Extracted verbatim from the native implementation so the web port
7
+ * (BottomSheet.web.tsx) shares the exact clamping behavior:
8
+ * - corner-resize math: BottomSheet.tsx createResizeHandler (lines ~767-869)
9
+ * - close heuristic: BottomSheet.tsx onPanResponderRelease (lines ~706-708)
10
+ * The native file still carries its own inline copy; if you change one,
11
+ * change both (candidate for a later native refactor to import this).
12
+ */
13
+
14
+ export const MIN_HEIGHT = 100;
15
+ export const DEFAULT_HEIGHT = 400;
16
+ export const FLOATING_WIDTH = 380;
17
+ export const FLOATING_HEIGHT = 500;
18
+ export const FLOATING_MIN_HEIGHT = 80;
19
+
20
+ /** Native: FLOATING_MIN_WIDTH = SCREEN.width * 0.25 */
21
+ export function floatingMinWidth(screenWidth) {
22
+ return screenWidth * 0.25;
23
+ }
24
+ /**
25
+ * 4-corner resize with safe-area-clamped bounds and min sizes.
26
+ * Mirrors the switch in the native createResizeHandler exactly.
27
+ */
28
+ export function resizeCorner(corner, start, dx, dy, container, insets, minWidth, minHeight = FLOATING_MIN_HEIGHT) {
29
+ const minLeft = Math.max(0, insets.left || 0);
30
+ const maxRight = container.width - Math.max(0, insets.right || 0);
31
+ const minTop = Math.max(0, insets.top || 0);
32
+ const maxBottom = container.height - Math.max(0, insets.bottom || 0);
33
+ const startRight = start.left + start.width;
34
+ const startBottom = start.top + start.height;
35
+ let left = start.left;
36
+ let top = start.top;
37
+ let right = startRight;
38
+ let bottom = startBottom;
39
+ switch (corner) {
40
+ case 'topLeft':
41
+ {
42
+ left = Math.max(minLeft, Math.min(start.left + dx, startRight - minWidth));
43
+ top = Math.max(minTop, Math.min(start.top + dy, startBottom - minHeight));
44
+ break;
45
+ }
46
+ case 'topRight':
47
+ {
48
+ right = Math.min(maxRight, Math.max(startRight + dx, start.left + minWidth));
49
+ top = Math.max(minTop, Math.min(start.top + dy, startBottom - minHeight));
50
+ break;
51
+ }
52
+ case 'bottomLeft':
53
+ {
54
+ left = Math.max(minLeft, Math.min(start.left + dx, startRight - minWidth));
55
+ bottom = Math.min(maxBottom, Math.max(startBottom + dy, start.top + minHeight));
56
+ break;
57
+ }
58
+ case 'bottomRight':
59
+ {
60
+ right = Math.min(maxRight, Math.max(startRight + dx, start.left + minWidth));
61
+ bottom = Math.min(maxBottom, Math.max(startBottom + dy, start.top + minHeight));
62
+ break;
63
+ }
64
+ }
65
+ return {
66
+ left,
67
+ top,
68
+ width: Math.max(minWidth, right - left),
69
+ height: Math.max(minHeight, bottom - top)
70
+ };
71
+ }
72
+
73
+ /**
74
+ * Drag-to-dismiss heuristic. Native units: vy in px/ms (RN gestureState.vy),
75
+ * dy total drag in px.
76
+ */
77
+ export function shouldCloseOnRelease(vy, dy, finalHeight, minHeight) {
78
+ return vy > 0.8 && dy > 50 || dy > 150 && finalHeight <= minHeight;
79
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Platform-free tap-count recognizer shared by the BottomSheet header and
5
+ * floating window: 2 taps toggles mode, 3+ closes. Mirrors the native
6
+ * implementation (BottomSheet.tsx ModalHeader.handleHeaderTap /
7
+ * handleFloatingTap): 500ms reset window, 300ms settle timer.
8
+ */
9
+ import { useEffect, useRef } from 'react';
10
+ export function useMultiTap(onDouble, onTriple) {
11
+ const lastTapRef = useRef(0);
12
+ const tapCountRef = useRef(0);
13
+ const timeoutRef = useRef(null);
14
+ // Latest-ref pattern so the returned handler stays stable without
15
+ // re-arming timers when callbacks change identity.
16
+ const handlersRef = useRef({
17
+ onDouble,
18
+ onTriple
19
+ });
20
+ handlersRef.current = {
21
+ onDouble,
22
+ onTriple
23
+ };
24
+ useEffect(() => {
25
+ return () => {
26
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
27
+ };
28
+ }, []);
29
+ const tapHandlerRef = useRef(() => {
30
+ const now = Date.now();
31
+ if (now - lastTapRef.current > 500) {
32
+ tapCountRef.current = 0;
33
+ }
34
+ tapCountRef.current++;
35
+ lastTapRef.current = now;
36
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
37
+ timeoutRef.current = setTimeout(() => {
38
+ if (tapCountRef.current === 2) {
39
+ handlersRef.current.onDouble();
40
+ } else if (tapCountRef.current >= 3) {
41
+ handlersRef.current.onTriple();
42
+ }
43
+ tapCountRef.current = 0;
44
+ }, 300);
45
+ });
46
+ return tapHandlerRef.current;
47
+ }
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+
3
+ // Web entry — reached via bundler alias (same pattern as
4
+ // @buoy-gg/core → devtools-floating-menu/src/index.web.tsx; the package
5
+ // exports map has no browser condition, so consumers alias this file).
6
+ export { BottomSheet } from './components/BottomSheet.web';
@@ -0,0 +1,75 @@
1
+ /**
2
+ * BottomSheet — Web renderer (React DOM).
3
+ *
4
+ * Same public API and behavior as the native BottomSheet.tsx:
5
+ * - two modes: "bottomSheet" (full-width, continuous drag-resize via header,
6
+ * fling-down to close) and "floating" (draggable window, 4-corner resize,
7
+ * tap topRight corner = close, tap topLeft = onBack)
8
+ * - double-tap header toggles mode, triple-tap closes
9
+ * - no backdrop; bottom-sheet container lets taps pass through beside it
10
+ *
11
+ * Web adaptations (each annotated inline with the native token it mirrors):
12
+ * - Pointer Events + setPointerCapture replace PanResponder (one code path
13
+ * for mouse and touch; capture gives "never release the responder"
14
+ * semantics). touch-action:none on gesture surfaces or WKWebView/Safari
15
+ * steals drags for page scroll.
16
+ * - During gestures we write styles directly to the DOM node (native rule:
17
+ * "direct setValue, no state updates") and commit to React state on release.
18
+ * - Native spring tension:180/friction:22 ≈ cubic-bezier(0.16,1,0.3,1) 320ms;
19
+ * the 200ms opacity fade is copied as-is.
20
+ * - Safe areas come from env(safe-area-inset-*) via a probe element (the
21
+ * native iPhone-dimension table is deleted). Requires viewport-fit=cover
22
+ * in the host page's <meta name="viewport"> to be non-zero on iOS.
23
+ * - Web-only additive props: `disableScrollWrapper` (tools with virtualized
24
+ * bodies need it — JsModal has it natively) and `zIndex` (AppHost stacking).
25
+ *
26
+ * Intentionally NOT ported: the visibility close animation on prop change —
27
+ * native returns null immediately when visible=false (only the gesture-close
28
+ * animates out), and we mirror that.
29
+ */
30
+ import { type CSSProperties, type ReactNode, type FC } from 'react';
31
+ declare const defaultTheme: {
32
+ background: string;
33
+ panel: string;
34
+ border: string;
35
+ primary: string;
36
+ secondary: string;
37
+ muted: string;
38
+ success: string;
39
+ error: string;
40
+ info: string;
41
+ };
42
+ export type BottomSheetMode = 'bottomSheet' | 'floating';
43
+ export interface BottomSheetHeaderConfig {
44
+ title?: string;
45
+ subtitle?: string;
46
+ customContent?: ReactNode;
47
+ hideCloseButton?: boolean;
48
+ }
49
+ interface CustomStyles {
50
+ container?: CSSProperties;
51
+ content?: CSSProperties;
52
+ }
53
+ export interface BottomSheetProps {
54
+ visible: boolean;
55
+ onClose: () => void;
56
+ children: ReactNode;
57
+ header?: BottomSheetHeaderConfig;
58
+ styles?: CustomStyles;
59
+ minHeight?: number;
60
+ maxHeight?: number;
61
+ initialHeight?: number;
62
+ initialMode?: BottomSheetMode;
63
+ onModeChange?: (mode: BottomSheetMode) => void;
64
+ footer?: ReactNode;
65
+ footerHeight?: number;
66
+ onBack?: () => void;
67
+ theme?: Partial<typeof defaultTheme>;
68
+ /** Web-only: render children without the scrolling wrapper (virtualized bodies). */
69
+ disableScrollWrapper?: boolean;
70
+ /** Web-only: stacking context for hosts (native hardcodes 1000). */
71
+ zIndex?: number;
72
+ }
73
+ export declare const BottomSheet: FC<BottomSheetProps>;
74
+ export {};
75
+ //# sourceMappingURL=BottomSheet.web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BottomSheet.web.d.ts","sourceRoot":"","sources":["../../../src/components/BottomSheet.web.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,EAAE,EAER,MAAM,OAAO,CAAC;AAoBf,QAAA,MAAM,YAAY;;;;;;;;;;CAUjB,CAAC;AAKF,MAAM,MAAM,eAAe,GAAG,aAAa,GAAG,UAAU,CAAC;AAEzD,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,UAAU,YAAY;IACpB,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;IAC/C,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC,OAAO,YAAY,CAAC,CAAC;IACrC,oFAAoF;IACpF,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA6tBD,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CA+D5C,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Platform-free geometry for the BottomSheet.
3
+ *
4
+ * Extracted verbatim from the native implementation so the web port
5
+ * (BottomSheet.web.tsx) shares the exact clamping behavior:
6
+ * - corner-resize math: BottomSheet.tsx createResizeHandler (lines ~767-869)
7
+ * - close heuristic: BottomSheet.tsx onPanResponderRelease (lines ~706-708)
8
+ * The native file still carries its own inline copy; if you change one,
9
+ * change both (candidate for a later native refactor to import this).
10
+ */
11
+ export declare const MIN_HEIGHT = 100;
12
+ export declare const DEFAULT_HEIGHT = 400;
13
+ export declare const FLOATING_WIDTH = 380;
14
+ export declare const FLOATING_HEIGHT = 500;
15
+ export declare const FLOATING_MIN_HEIGHT = 80;
16
+ /** Native: FLOATING_MIN_WIDTH = SCREEN.width * 0.25 */
17
+ export declare function floatingMinWidth(screenWidth: number): number;
18
+ export type Corner = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight';
19
+ export interface Rect {
20
+ left: number;
21
+ top: number;
22
+ width: number;
23
+ height: number;
24
+ }
25
+ export interface Insets {
26
+ top: number;
27
+ bottom: number;
28
+ left: number;
29
+ right: number;
30
+ }
31
+ /**
32
+ * 4-corner resize with safe-area-clamped bounds and min sizes.
33
+ * Mirrors the switch in the native createResizeHandler exactly.
34
+ */
35
+ export declare function resizeCorner(corner: Corner, start: Rect, dx: number, dy: number, container: {
36
+ width: number;
37
+ height: number;
38
+ }, insets: Insets, minWidth: number, minHeight?: number): Rect;
39
+ /**
40
+ * Drag-to-dismiss heuristic. Native units: vy in px/ms (RN gestureState.vy),
41
+ * dy total drag in px.
42
+ */
43
+ export declare function shouldCloseOnRelease(vy: number, dy: number, finalHeight: number, minHeight: number): boolean;
44
+ //# sourceMappingURL=bottomSheetGeometry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bottomSheetGeometry.d.ts","sourceRoot":"","sources":["../../../src/components/bottomSheetGeometry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,eAAO,MAAM,UAAU,MAAM,CAAC;AAC9B,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,eAAO,MAAM,eAAe,MAAM,CAAC;AACnC,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC,uDAAuD;AACvD,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,MAAM,MAAM,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,YAAY,GAAG,aAAa,CAAC;AAE3E,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,MAAM;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,IAAI,EACX,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,SAAS,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAC5C,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAA4B,GACtC,IAAI,CA2CN;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAET"}
@@ -0,0 +1,2 @@
1
+ export declare function useMultiTap(onDouble: () => void, onTriple: () => void): () => void;
2
+ //# sourceMappingURL=useMultiTap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMultiTap.d.ts","sourceRoot":"","sources":["../../../src/components/useMultiTap.ts"],"names":[],"mappings":"AAQA,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,cAmCrE"}
@@ -0,0 +1,3 @@
1
+ export { BottomSheet } from './components/BottomSheet.web';
2
+ export type { BottomSheetProps, BottomSheetMode, BottomSheetHeaderConfig, } from './components/BottomSheet.web';
3
+ //# sourceMappingURL=index.web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.web.d.ts","sourceRoot":"","sources":["../../src/index.web.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,uBAAuB,GACxB,MAAM,8BAA8B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buoy-gg/bottom-sheet",
3
- "version": "7.0.15",
3
+ "version": "7.0.17",
4
4
  "description": "High-performance bottom sheet & floating window component for React Native — 60 FPS native-driver animations, fully customizable.",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -26,7 +26,7 @@
26
26
  ],
27
27
  "sideEffects": false,
28
28
  "dependencies": {
29
- "@buoy-gg/shared-ui": "^7.0.15"
29
+ "@buoy-gg/shared-ui": "^7.0.17"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "react": "*",