@ttt-productions/mobile-core 0.0.1 → 0.0.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.
Files changed (73) hide show
  1. package/dist/env.d.ts +5 -0
  2. package/dist/env.d.ts.map +1 -0
  3. package/{src/env.ts → dist/env.js} +1 -0
  4. package/dist/env.js.map +1 -0
  5. package/dist/index.d.ts +14 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/{src/index.ts → dist/index.js} +1 -5
  8. package/dist/index.js.map +1 -0
  9. package/dist/ios/useIosSafariFixes.d.ts +8 -0
  10. package/dist/ios/useIosSafariFixes.d.ts.map +1 -0
  11. package/{src/ios/useIosSafariFixes.ts → dist/ios/useIosSafariFixes.js} +7 -7
  12. package/dist/ios/useIosSafariFixes.js.map +1 -0
  13. package/dist/ios/useNoRubberBand.d.ts +6 -0
  14. package/dist/ios/useNoRubberBand.d.ts.map +1 -0
  15. package/dist/ios/useNoRubberBand.js +19 -0
  16. package/dist/ios/useNoRubberBand.js.map +1 -0
  17. package/dist/keyboard/KeyboardAvoidingView.d.ts +18 -0
  18. package/dist/keyboard/KeyboardAvoidingView.d.ts.map +1 -0
  19. package/dist/keyboard/KeyboardAvoidingView.js +11 -0
  20. package/dist/keyboard/KeyboardAvoidingView.js.map +1 -0
  21. package/dist/keyboard/focusOrder.d.ts +2 -0
  22. package/dist/keyboard/focusOrder.d.ts.map +1 -0
  23. package/dist/keyboard/focusOrder.js +18 -0
  24. package/dist/keyboard/focusOrder.js.map +1 -0
  25. package/dist/keyboard/useInputNavigation.d.ts +17 -0
  26. package/dist/keyboard/useInputNavigation.d.ts.map +1 -0
  27. package/dist/keyboard/useInputNavigation.js +35 -0
  28. package/dist/keyboard/useInputNavigation.js.map +1 -0
  29. package/dist/keyboard/useKeepFocusedInputVisible.d.ts +9 -0
  30. package/dist/keyboard/useKeepFocusedInputVisible.d.ts.map +1 -0
  31. package/dist/keyboard/useKeepFocusedInputVisible.js +36 -0
  32. package/dist/keyboard/useKeepFocusedInputVisible.js.map +1 -0
  33. package/dist/keyboard/useKeyboard.d.ts +8 -0
  34. package/dist/keyboard/useKeyboard.d.ts.map +1 -0
  35. package/dist/keyboard/useKeyboard.js +66 -0
  36. package/dist/keyboard/useKeyboard.js.map +1 -0
  37. package/dist/safe-area/SafeArea.d.ts +10 -0
  38. package/dist/safe-area/SafeArea.d.ts.map +1 -0
  39. package/dist/safe-area/SafeArea.js +11 -0
  40. package/dist/safe-area/SafeArea.js.map +1 -0
  41. package/dist/safe-area/useSafeAreaInsets.d.ts +7 -0
  42. package/dist/safe-area/useSafeAreaInsets.d.ts.map +1 -0
  43. package/dist/safe-area/useSafeAreaInsets.js +38 -0
  44. package/dist/safe-area/useSafeAreaInsets.js.map +1 -0
  45. package/dist/scroll/useScrollLock.d.ts +7 -0
  46. package/dist/scroll/useScrollLock.d.ts.map +1 -0
  47. package/dist/scroll/useScrollLock.js +35 -0
  48. package/dist/scroll/useScrollLock.js.map +1 -0
  49. package/dist/types.d.ts +12 -0
  50. package/dist/types.d.ts.map +1 -0
  51. package/dist/types.js +2 -0
  52. package/dist/types.js.map +1 -0
  53. package/dist/viewport/useViewportHeightVars.d.ts +10 -0
  54. package/dist/viewport/useViewportHeightVars.d.ts.map +1 -0
  55. package/dist/viewport/useViewportHeightVars.js +30 -0
  56. package/dist/viewport/useViewportHeightVars.js.map +1 -0
  57. package/dist/viewport/useVisualViewport.d.ts +11 -0
  58. package/dist/viewport/useVisualViewport.d.ts.map +1 -0
  59. package/dist/viewport/useVisualViewport.js +36 -0
  60. package/dist/viewport/useVisualViewport.js.map +1 -0
  61. package/package.json +41 -18
  62. package/src/ios/useNoRubberBand.ts +0 -20
  63. package/src/keyboard/KeyboardAvoidingView.tsx +0 -24
  64. package/src/keyboard/focusOrder.ts +0 -20
  65. package/src/keyboard/useInputNavigation.ts +0 -44
  66. package/src/keyboard/useKeepFocusedInputVisible.ts +0 -41
  67. package/src/keyboard/useKeyboard.ts +0 -74
  68. package/src/safe-area/SafeArea.tsx +0 -23
  69. package/src/safe-area/useSafeAreaInsets.ts +0 -44
  70. package/src/scroll/useScrollLock.ts +0 -37
  71. package/src/types.ts +0 -8
  72. package/src/viewport/useViewportHeightVars.ts +0 -32
  73. package/src/viewport/useVisualViewport.ts +0 -42
package/dist/env.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export declare const isBrowser: boolean;
2
+ export declare const isIOS: boolean;
3
+ export declare const isSafari: boolean;
4
+ export declare const hasVisualViewport: boolean;
5
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,SAAmE,CAAC;AAC1F,eAAO,MAAM,KAAK,SAA0D,CAAC;AAC7E,eAAO,MAAM,QAAQ,SAA0E,CAAC;AAChG,eAAO,MAAM,iBAAiB,SAAuC,CAAC"}
@@ -2,3 +2,4 @@ export const isBrowser = typeof window !== "undefined" && typeof document !== "u
2
2
  export const isIOS = isBrowser && /iP(ad|hone|od)/.test(navigator.userAgent);
3
3
  export const isSafari = isBrowser && /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
4
4
  export const hasVisualViewport = isBrowser && !!window.visualViewport;
5
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,QAAQ,KAAK,WAAW,CAAC;AAC1F,MAAM,CAAC,MAAM,KAAK,GAAG,SAAS,IAAI,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;AAC7E,MAAM,CAAC,MAAM,QAAQ,GAAG,SAAS,IAAI,gCAAgC,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;AAChG,MAAM,CAAC,MAAM,iBAAiB,GAAG,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC"}
@@ -0,0 +1,14 @@
1
+ export * from "./types";
2
+ export * from "./env";
3
+ export * from "./viewport/useVisualViewport";
4
+ export * from "./viewport/useViewportHeightVars";
5
+ export * from "./keyboard/useKeyboard";
6
+ export * from "./keyboard/useKeepFocusedInputVisible";
7
+ export * from "./keyboard/useInputNavigation";
8
+ export * from "./keyboard/KeyboardAvoidingView";
9
+ export * from "./safe-area/useSafeAreaInsets";
10
+ export * from "./safe-area/SafeArea";
11
+ export * from "./scroll/useScrollLock";
12
+ export * from "./ios/useIosSafariFixes";
13
+ export * from "./ios/useNoRubberBand";
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,OAAO,CAAC;AAEtB,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AAEjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,uCAAuC,CAAC;AACtD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAEhD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,sBAAsB,CAAC;AAErC,cAAc,wBAAwB,CAAC;AAEvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC"}
@@ -1,18 +1,14 @@
1
1
  export * from "./types";
2
2
  export * from "./env";
3
-
4
3
  export * from "./viewport/useVisualViewport";
5
4
  export * from "./viewport/useViewportHeightVars";
6
-
7
5
  export * from "./keyboard/useKeyboard";
8
6
  export * from "./keyboard/useKeepFocusedInputVisible";
9
7
  export * from "./keyboard/useInputNavigation";
10
8
  export * from "./keyboard/KeyboardAvoidingView";
11
-
12
9
  export * from "./safe-area/useSafeAreaInsets";
13
10
  export * from "./safe-area/SafeArea";
14
-
15
11
  export * from "./scroll/useScrollLock";
16
-
17
12
  export * from "./ios/useIosSafariFixes";
18
13
  export * from "./ios/useNoRubberBand";
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,OAAO,CAAC;AAEtB,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AAEjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,uCAAuC,CAAC;AACtD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAEhD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,sBAAsB,CAAC;AAErC,cAAc,wBAAwB,CAAC;AAEvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Small, safe iOS Safari fixes:
3
+ * - disables double-tap-to-zoom delays for buttons (via touch-action)
4
+ * - ensures inputs don't auto-zoom by recommending 16px font (cannot enforce here)
5
+ * - adds -webkit-overflow-scrolling: touch helper class hook (optional)
6
+ */
7
+ export declare function useIosSafariFixes(): void;
8
+ //# sourceMappingURL=useIosSafariFixes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useIosSafariFixes.d.ts","sourceRoot":"","sources":["../../src/ios/useIosSafariFixes.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,wBAAgB,iBAAiB,SAOhC"}
@@ -1,6 +1,5 @@
1
1
  import { useEffect } from "react";
2
2
  import { isBrowser, isIOS, isSafari } from "../env";
3
-
4
3
  /**
5
4
  * Small, safe iOS Safari fixes:
6
5
  * - disables double-tap-to-zoom delays for buttons (via touch-action)
@@ -8,10 +7,11 @@ import { isBrowser, isIOS, isSafari } from "../env";
8
7
  * - adds -webkit-overflow-scrolling: touch helper class hook (optional)
9
8
  */
10
9
  export function useIosSafariFixes() {
11
- useEffect(() => {
12
- if (!isBrowser || !isIOS || !isSafari) return;
13
-
14
- document.documentElement.classList.add("ttt-ios-safari");
15
- return () => document.documentElement.classList.remove("ttt-ios-safari");
16
- }, []);
10
+ useEffect(() => {
11
+ if (!isBrowser || !isIOS || !isSafari)
12
+ return;
13
+ document.documentElement.classList.add("ttt-ios-safari");
14
+ return () => document.documentElement.classList.remove("ttt-ios-safari");
15
+ }, []);
17
16
  }
17
+ //# sourceMappingURL=useIosSafariFixes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useIosSafariFixes.js","sourceRoot":"","sources":["../../src/ios/useIosSafariFixes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB;IAC/B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ;YAAE,OAAO;QAE9C,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QACzD,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAC3E,CAAC,EAAE,EAAE,CAAC,CAAC;AACT,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Prevents iOS rubber-band scroll on the document by limiting overscroll chaining.
3
+ * Use sparingly (e.g., full-screen experiences).
4
+ */
5
+ export declare function useNoRubberBand(enabled: boolean): void;
6
+ //# sourceMappingURL=useNoRubberBand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useNoRubberBand.d.ts","sourceRoot":"","sources":["../../src/ios/useNoRubberBand.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,QAY/C"}
@@ -0,0 +1,19 @@
1
+ import { useEffect } from "react";
2
+ import { isBrowser, isIOS } from "../env";
3
+ /**
4
+ * Prevents iOS rubber-band scroll on the document by limiting overscroll chaining.
5
+ * Use sparingly (e.g., full-screen experiences).
6
+ */
7
+ export function useNoRubberBand(enabled) {
8
+ useEffect(() => {
9
+ if (!isBrowser || !isIOS || !enabled)
10
+ return;
11
+ const el = document.documentElement;
12
+ const prev = el.style.overscrollBehaviorY;
13
+ el.style.overscrollBehaviorY = "none";
14
+ return () => {
15
+ el.style.overscrollBehaviorY = prev;
16
+ };
17
+ }, [enabled]);
18
+ }
19
+ //# sourceMappingURL=useNoRubberBand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useNoRubberBand.js","sourceRoot":"","sources":["../../src/ios/useNoRubberBand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAE1C;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO;YAAE,OAAO;QAE7C,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;QACpC,MAAM,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,mBAA0B,CAAC;QAChD,EAAE,CAAC,KAAa,CAAC,mBAAmB,GAAG,MAAM,CAAC;QAE/C,OAAO,GAAG,EAAE;YACT,EAAE,CAAC,KAAa,CAAC,mBAAmB,GAAG,IAAI,CAAC;QAC/C,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;AAChB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import React from "react";
2
+ type Props = React.HTMLAttributes<HTMLDivElement> & {
3
+ /**
4
+ * If true, adds padding-bottom equal to keyboard height while open.
5
+ * Good default for forms.
6
+ */
7
+ padding?: boolean;
8
+ /**
9
+ * Adds extra px to bottom padding.
10
+ */
11
+ offset?: number;
12
+ };
13
+ /**
14
+ * Desktop-safe: does nothing when keyboard is not detected.
15
+ */
16
+ export declare function KeyboardAvoidingView({ padding, offset, style, ...rest }: Props): import("react/jsx-runtime").JSX.Element;
17
+ export {};
18
+ //# sourceMappingURL=KeyboardAvoidingView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KeyboardAvoidingView.d.ts","sourceRoot":"","sources":["../../src/keyboard/KeyboardAvoidingView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,KAAK,KAAK,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG;IAClD;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,OAAc,EAAE,MAAU,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CAKzF"}
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useKeyboard } from "./useKeyboard";
3
+ /**
4
+ * Desktop-safe: does nothing when keyboard is not detected.
5
+ */
6
+ export function KeyboardAvoidingView({ padding = true, offset = 0, style, ...rest }) {
7
+ const k = useKeyboard();
8
+ const pb = padding && k.isOpen ? k.height + offset : 0;
9
+ return _jsx("div", { ...rest, style: { ...style, paddingBottom: style?.paddingBottom ?? pb } });
10
+ }
11
+ //# sourceMappingURL=KeyboardAvoidingView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KeyboardAvoidingView.js","sourceRoot":"","sources":["../../src/keyboard/KeyboardAvoidingView.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAc5C;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,EAAE,OAAO,GAAG,IAAI,EAAE,MAAM,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,IAAI,EAAS;IACxF,MAAM,CAAC,GAAG,WAAW,EAAE,CAAC;IACxB,MAAM,EAAE,GAAG,OAAO,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAEvD,OAAO,iBAAS,IAAI,EAAE,KAAK,EAAE,EAAE,GAAG,KAAK,EAAE,aAAa,EAAG,KAAa,EAAE,aAAa,IAAI,EAAE,EAAE,GAAI,CAAC;AACpG,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function getFocusableInputs(root?: HTMLElement | Document): HTMLElement[];
2
+ //# sourceMappingURL=focusOrder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"focusOrder.d.ts","sourceRoot":"","sources":["../../src/keyboard/focusOrder.ts"],"names":[],"mappings":"AAAA,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,WAAW,GAAG,QAAmB,iBAmBzE"}
@@ -0,0 +1,18 @@
1
+ export function getFocusableInputs(root = document) {
2
+ const el = root instanceof Document ? root : root;
3
+ const list = Array.from(el.querySelectorAll('input, textarea, select, [contenteditable="true"], [data-ttt-input]')).filter((n) => !n.hasAttribute("disabled") && n.tabIndex !== -1);
4
+ // DOM order is usually correct; allow explicit override
5
+ list.sort((a, b) => {
6
+ const ao = Number(a.getAttribute("data-input-order") ?? "0");
7
+ const bo = Number(b.getAttribute("data-input-order") ?? "0");
8
+ if (ao && bo)
9
+ return ao - bo;
10
+ if (ao)
11
+ return -1;
12
+ if (bo)
13
+ return 1;
14
+ return 0;
15
+ });
16
+ return list;
17
+ }
18
+ //# sourceMappingURL=focusOrder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"focusOrder.js","sourceRoot":"","sources":["../../src/keyboard/focusOrder.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,kBAAkB,CAAC,OAA+B,QAAQ;IACxE,MAAM,EAAE,GAAG,IAAI,YAAY,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAClD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CACrB,EAAE,CAAC,gBAAgB,CACjB,qEAAqE,CACtE,CACF,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC;IAElE,wDAAwD;IACxD,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACjB,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,kBAAkB,CAAC,IAAI,GAAG,CAAC,CAAC;QAC7D,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,kBAAkB,CAAC,IAAI,GAAG,CAAC,CAAC;QAC7D,IAAI,EAAE,IAAI,EAAE;YAAE,OAAO,EAAE,GAAG,EAAE,CAAC;QAC7B,IAAI,EAAE;YAAE,OAAO,CAAC,CAAC,CAAC;QAClB,IAAI,EAAE;YAAE,OAAO,CAAC,CAAC;QACjB,OAAO,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,17 @@
1
+ type Options = {
2
+ root?: HTMLElement | null;
3
+ onDone?: () => void;
4
+ };
5
+ /**
6
+ * Attach to inputs:
7
+ * onKeyDown={nav.onKeyDown}
8
+ * onSubmitEditing={nav.onSubmitEditing} (optional)
9
+ *
10
+ * Also supports explicit ordering via data-input-order.
11
+ */
12
+ export declare function useInputNavigation(opts?: Options): {
13
+ focusNext: () => void;
14
+ onKeyDown: (e: React.KeyboardEvent) => void;
15
+ };
16
+ export {};
17
+ //# sourceMappingURL=useInputNavigation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useInputNavigation.d.ts","sourceRoot":"","sources":["../../src/keyboard/useInputNavigation.ts"],"names":[],"mappings":"AAGA,KAAK,OAAO,GAAG;IACb,IAAI,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,CAAC,EAAE,OAAO;;mBAezC,KAAK,CAAC,aAAa;EAa1B"}
@@ -0,0 +1,35 @@
1
+ import { useCallback } from "react";
2
+ import { getFocusableInputs } from "./focusOrder";
3
+ /**
4
+ * Attach to inputs:
5
+ * onKeyDown={nav.onKeyDown}
6
+ * onSubmitEditing={nav.onSubmitEditing} (optional)
7
+ *
8
+ * Also supports explicit ordering via data-input-order.
9
+ */
10
+ export function useInputNavigation(opts) {
11
+ const root = opts?.root ?? null;
12
+ const focusNext = useCallback(() => {
13
+ const scope = root ?? document;
14
+ const inputs = getFocusableInputs(scope);
15
+ const active = document.activeElement;
16
+ const idx = active ? inputs.indexOf(active) : -1;
17
+ const next = inputs[idx + 1];
18
+ if (next)
19
+ next.focus();
20
+ else
21
+ opts?.onDone?.();
22
+ }, [root, opts]);
23
+ const onKeyDown = useCallback((e) => {
24
+ if (e.key === "Enter") {
25
+ // allow textarea newlines
26
+ const el = e.currentTarget;
27
+ if (el.tagName.toLowerCase() === "textarea")
28
+ return;
29
+ e.preventDefault();
30
+ focusNext();
31
+ }
32
+ }, [focusNext]);
33
+ return { focusNext, onKeyDown };
34
+ }
35
+ //# sourceMappingURL=useInputNavigation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useInputNavigation.js","sourceRoot":"","sources":["../../src/keyboard/useInputNavigation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAOlD;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAc;IAC/C,MAAM,IAAI,GAAG,IAAI,EAAE,IAAI,IAAI,IAAI,CAAC;IAEhC,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;QACjC,MAAM,KAAK,GAAG,IAAI,IAAI,QAAQ,CAAC;QAC/B,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAY,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAmC,CAAC;QAC5D,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QAE7B,IAAI,IAAI;YAAE,IAAI,CAAC,KAAK,EAAE,CAAC;;YAClB,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;IACxB,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAEjB,MAAM,SAAS,GAAG,WAAW,CAC3B,CAAC,CAAsB,EAAE,EAAE;QACzB,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;YACtB,0BAA0B;YAC1B,MAAM,EAAE,GAAG,CAAC,CAAC,aAA4B,CAAC;YAC1C,IAAI,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,UAAU;gBAAE,OAAO;YACpD,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,SAAS,EAAE,CAAC;QACd,CAAC;IACH,CAAC,EACD,CAAC,SAAS,CAAC,CACZ,CAAC;IAEF,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;AAClC,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * When keyboard opens, ensure focused element is visible within visual viewport.
3
+ * - iOS Safari often hides the caret behind the keyboard.
4
+ */
5
+ export declare function useKeepFocusedInputVisible(opts?: {
6
+ extraOffset?: number;
7
+ scrollBehavior?: ScrollBehavior;
8
+ }): void;
9
+ //# sourceMappingURL=useKeepFocusedInputVisible.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useKeepFocusedInputVisible.d.ts","sourceRoot":"","sources":["../../src/keyboard/useKeepFocusedInputVisible.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,CAAC,EAAE;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC,QA6BA"}
@@ -0,0 +1,36 @@
1
+ import { useEffect } from "react";
2
+ import { isBrowser } from "../env";
3
+ import { useKeyboard } from "./useKeyboard";
4
+ /**
5
+ * When keyboard opens, ensure focused element is visible within visual viewport.
6
+ * - iOS Safari often hides the caret behind the keyboard.
7
+ */
8
+ export function useKeepFocusedInputVisible(opts) {
9
+ const { isOpen } = useKeyboard();
10
+ const extraOffset = opts?.extraOffset ?? 12;
11
+ const behavior = opts?.scrollBehavior ?? "smooth";
12
+ useEffect(() => {
13
+ if (!isBrowser)
14
+ return;
15
+ if (!isOpen)
16
+ return;
17
+ const el = document.activeElement;
18
+ if (!el)
19
+ return;
20
+ // only inputs-ish
21
+ const tag = el.tagName.toLowerCase();
22
+ const isInput = tag === "input" || tag === "textarea" || tag === "select" || el.isContentEditable || el.hasAttribute("data-ttt-input");
23
+ if (!isInput)
24
+ return;
25
+ const vv = window.visualViewport;
26
+ const vvH = vv?.height ?? window.innerHeight;
27
+ const rect = el.getBoundingClientRect();
28
+ const bottom = rect.bottom;
29
+ const limit = vvH - extraOffset;
30
+ if (bottom > limit) {
31
+ const delta = bottom - limit;
32
+ window.scrollBy({ top: delta, behavior });
33
+ }
34
+ }, [isOpen, extraOffset, behavior]);
35
+ }
36
+ //# sourceMappingURL=useKeepFocusedInputVisible.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useKeepFocusedInputVisible.js","sourceRoot":"","sources":["../../src/keyboard/useKeepFocusedInputVisible.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C;;;GAGG;AACH,MAAM,UAAU,0BAA0B,CAAC,IAG1C;IACC,MAAM,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;IACjC,MAAM,WAAW,GAAG,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC;IAC5C,MAAM,QAAQ,GAAG,IAAI,EAAE,cAAc,IAAI,QAAQ,CAAC;IAElD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,SAAS;YAAE,OAAO;QACvB,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,MAAM,EAAE,GAAG,QAAQ,CAAC,aAAmC,CAAC;QACxD,IAAI,CAAC,EAAE;YAAE,OAAO;QAEhB,kBAAkB;QAClB,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,OAAO,GACX,GAAG,KAAK,OAAO,IAAI,GAAG,KAAK,UAAU,IAAI,GAAG,KAAK,QAAQ,IAAI,EAAE,CAAC,iBAAiB,IAAI,EAAE,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;QACzH,IAAI,CAAC,OAAO;YAAE,OAAO;QAErB,MAAM,EAAE,GAAG,MAAM,CAAC,cAAc,CAAC;QACjC,MAAM,GAAG,GAAG,EAAE,EAAE,MAAM,IAAI,MAAM,CAAC,WAAW,CAAC;QAC7C,MAAM,IAAI,GAAG,EAAE,CAAC,qBAAqB,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,MAAM,KAAK,GAAG,GAAG,GAAG,WAAW,CAAC;QAEhC,IAAI,MAAM,GAAG,KAAK,EAAE,CAAC;YACnB,MAAM,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;YAC7B,MAAM,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;AACtC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { KeyboardState } from "../types";
2
+ /**
3
+ * Best effort keyboard detection:
4
+ * - iOS Safari: visualViewport.height shrinks when keyboard shows
5
+ * - fallback: focusin/focusout heuristics + innerHeight snapshots
6
+ */
7
+ export declare function useKeyboard(): KeyboardState;
8
+ //# sourceMappingURL=useKeyboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useKeyboard.d.ts","sourceRoot":"","sources":["../../src/keyboard/useKeyboard.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C;;;;GAIG;AACH,wBAAgB,WAAW,IAAI,aAAa,CAgE3C"}
@@ -0,0 +1,66 @@
1
+ import { useEffect, useMemo, useState } from "react";
2
+ import { hasVisualViewport, isBrowser } from "../env";
3
+ /**
4
+ * Best effort keyboard detection:
5
+ * - iOS Safari: visualViewport.height shrinks when keyboard shows
6
+ * - fallback: focusin/focusout heuristics + innerHeight snapshots
7
+ */
8
+ export function useKeyboard() {
9
+ const [baseline, setBaseline] = useState(() => (isBrowser ? window.innerHeight : 0));
10
+ const [height, setHeight] = useState(0);
11
+ const [open, setOpen] = useState(false);
12
+ const [source, setSource] = useState("fallback");
13
+ useEffect(() => {
14
+ if (!isBrowser)
15
+ return;
16
+ const setBaseIfNeeded = () => {
17
+ // update baseline when keyboard likely closed
18
+ const vvH = window.visualViewport?.height ?? window.innerHeight;
19
+ const inner = window.innerHeight;
20
+ const candidate = Math.max(vvH, inner);
21
+ setBaseline((b) => (Math.abs(candidate - b) > 40 ? candidate : b));
22
+ };
23
+ const onVV = () => {
24
+ const vvH = window.visualViewport?.height ?? window.innerHeight;
25
+ const delta = Math.max(0, Math.round(baseline - vvH));
26
+ const isOpen = delta > 80; // threshold
27
+ setSource("visualViewport");
28
+ setHeight(isOpen ? delta : 0);
29
+ setOpen(isOpen);
30
+ if (!isOpen)
31
+ setBaseIfNeeded();
32
+ };
33
+ const onFocusIn = () => {
34
+ // baseline snapshot on focus to reduce false positives
35
+ setBaseline((b) => Math.max(b, window.innerHeight));
36
+ };
37
+ const onFocusOut = () => {
38
+ // allow baseline update shortly after blur
39
+ setTimeout(setBaseIfNeeded, 50);
40
+ setTimeout(() => {
41
+ setOpen(false);
42
+ setHeight(0);
43
+ }, 250);
44
+ };
45
+ if (hasVisualViewport) {
46
+ window.visualViewport.addEventListener("resize", onVV, { passive: true });
47
+ window.visualViewport.addEventListener("scroll", onVV, { passive: true });
48
+ onVV();
49
+ }
50
+ window.addEventListener("focusin", onFocusIn, { passive: true });
51
+ window.addEventListener("focusout", onFocusOut, { passive: true });
52
+ window.addEventListener("orientationchange", setBaseIfNeeded, { passive: true });
53
+ setBaseIfNeeded();
54
+ return () => {
55
+ if (hasVisualViewport) {
56
+ window.visualViewport.removeEventListener("resize", onVV);
57
+ window.visualViewport.removeEventListener("scroll", onVV);
58
+ }
59
+ window.removeEventListener("focusin", onFocusIn);
60
+ window.removeEventListener("focusout", onFocusOut);
61
+ window.removeEventListener("orientationchange", setBaseIfNeeded);
62
+ };
63
+ }, [baseline]);
64
+ return useMemo(() => ({ isOpen: open, height, source }), [open, height, source]);
65
+ }
66
+ //# sourceMappingURL=useKeyboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useKeyboard.js","sourceRoot":"","sources":["../../src/keyboard/useKeyboard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ type Props = React.HTMLAttributes<HTMLDivElement> & {
3
+ top?: boolean;
4
+ bottom?: boolean;
5
+ left?: boolean;
6
+ right?: boolean;
7
+ };
8
+ export declare function SafeArea({ top, bottom, left, right, style, ...rest }: Props): import("react/jsx-runtime").JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=SafeArea.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SafeArea.d.ts","sourceRoot":"","sources":["../../src/safe-area/SafeArea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,KAAK,KAAK,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG;IAClD,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,wBAAgB,QAAQ,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE,KAAK,2CAa3E"}
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export function SafeArea({ top, bottom, left, right, style, ...rest }) {
3
+ return (_jsx("div", { ...rest, style: {
4
+ ...style,
5
+ paddingTop: top ? "env(safe-area-inset-top)" : style?.paddingTop,
6
+ paddingBottom: bottom ? "env(safe-area-inset-bottom)" : style?.paddingBottom,
7
+ paddingLeft: left ? "env(safe-area-inset-left)" : style?.paddingLeft,
8
+ paddingRight: right ? "env(safe-area-inset-right)" : style?.paddingRight,
9
+ } }));
10
+ }
11
+ //# sourceMappingURL=SafeArea.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SafeArea.js","sourceRoot":"","sources":["../../src/safe-area/SafeArea.tsx"],"names":[],"mappings":";AASA,MAAM,UAAU,QAAQ,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,IAAI,EAAS;IAC1E,OAAO,CACL,iBACM,IAAI,EACR,KAAK,EAAE;YACL,GAAG,KAAK;YACR,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAE,KAAa,EAAE,UAAU;YACzE,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAE,KAAa,EAAE,aAAa;YACrF,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAE,KAAa,EAAE,WAAW;YAC7E,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAE,KAAa,EAAE,YAAY;SAClF,GACD,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { Insets } from "../types";
2
+ /**
3
+ * Uses CSS env(safe-area-inset-*) by writing them to CSS vars and reading computed values.
4
+ * Works on iOS Safari; harmless elsewhere.
5
+ */
6
+ export declare function useSafeAreaInsets(): Insets;
7
+ //# sourceMappingURL=useSafeAreaInsets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSafeAreaInsets.d.ts","sourceRoot":"","sources":["../../src/safe-area/useSafeAreaInsets.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGvC;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAmC1C"}
@@ -0,0 +1,38 @@
1
+ import { useEffect, useState } from "react";
2
+ import { isBrowser } from "../env";
3
+ /**
4
+ * Uses CSS env(safe-area-inset-*) by writing them to CSS vars and reading computed values.
5
+ * Works on iOS Safari; harmless elsewhere.
6
+ */
7
+ export function useSafeAreaInsets() {
8
+ const [insets, setInsets] = useState({ top: 0, right: 0, bottom: 0, left: 0 });
9
+ useEffect(() => {
10
+ if (!isBrowser)
11
+ return;
12
+ const el = document.documentElement;
13
+ // set vars once
14
+ el.style.setProperty("--ttt-sai-top", "env(safe-area-inset-top)");
15
+ el.style.setProperty("--ttt-sai-right", "env(safe-area-inset-right)");
16
+ el.style.setProperty("--ttt-sai-bottom", "env(safe-area-inset-bottom)");
17
+ el.style.setProperty("--ttt-sai-left", "env(safe-area-inset-left)");
18
+ const read = () => {
19
+ const cs = getComputedStyle(el);
20
+ const px = (v) => Math.max(0, Math.round(parseFloat(v || "0")));
21
+ setInsets({
22
+ top: px(cs.getPropertyValue("--ttt-sai-top")),
23
+ right: px(cs.getPropertyValue("--ttt-sai-right")),
24
+ bottom: px(cs.getPropertyValue("--ttt-sai-bottom")),
25
+ left: px(cs.getPropertyValue("--ttt-sai-left")),
26
+ });
27
+ };
28
+ read();
29
+ window.addEventListener("resize", read, { passive: true });
30
+ window.addEventListener("orientationchange", read, { passive: true });
31
+ return () => {
32
+ window.removeEventListener("resize", read);
33
+ window.removeEventListener("orientationchange", read);
34
+ };
35
+ }, []);
36
+ return insets;
37
+ }
38
+ //# sourceMappingURL=useSafeAreaInsets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSafeAreaInsets.js","sourceRoot":"","sources":["../../src/safe-area/useSafeAreaInsets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEnC;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAS,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;IAEvF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,SAAS;YAAE,OAAO;QAEvB,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;QAEpC,gBAAgB;QAChB,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,eAAe,EAAE,0BAA0B,CAAC,CAAC;QAClE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,iBAAiB,EAAE,4BAA4B,CAAC,CAAC;QACtE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,kBAAkB,EAAE,6BAA6B,CAAC,CAAC;QACxE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,gBAAgB,EAAE,2BAA2B,CAAC,CAAC;QAEpE,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,MAAM,EAAE,GAAG,gBAAgB,CAAC,EAAE,CAAC,CAAC;YAChC,MAAM,EAAE,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;YACxE,SAAS,CAAC;gBACR,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC;gBAC7C,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;gBACjD,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,CAAC;gBACnD,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;aAChD,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,IAAI,EAAE,CAAC;QACP,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,MAAM,CAAC,gBAAgB,CAAC,mBAAmB,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACtE,OAAO,GAAG,EAAE;YACV,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAC3C,MAAM,CAAC,mBAAmB,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC;QACxD,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Locks body scroll (mobile sheet/modal fix).
3
+ * - preserves current scroll position
4
+ * - iOS safe enough for common cases
5
+ */
6
+ export declare function useScrollLock(locked: boolean): void;
7
+ //# sourceMappingURL=useScrollLock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useScrollLock.d.ts","sourceRoot":"","sources":["../../src/scroll/useScrollLock.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,QA4B5C"}
@@ -0,0 +1,35 @@
1
+ import { useEffect } from "react";
2
+ import { isBrowser } from "../env";
3
+ /**
4
+ * Locks body scroll (mobile sheet/modal fix).
5
+ * - preserves current scroll position
6
+ * - iOS safe enough for common cases
7
+ */
8
+ export function useScrollLock(locked) {
9
+ useEffect(() => {
10
+ if (!isBrowser)
11
+ return;
12
+ if (!locked)
13
+ return;
14
+ const { body } = document;
15
+ const scrollY = window.scrollY;
16
+ const prev = {
17
+ position: body.style.position,
18
+ top: body.style.top,
19
+ width: body.style.width,
20
+ overflowY: body.style.overflowY,
21
+ };
22
+ body.style.position = "fixed";
23
+ body.style.top = `-${scrollY}px`;
24
+ body.style.width = "100%";
25
+ body.style.overflowY = "scroll";
26
+ return () => {
27
+ body.style.position = prev.position;
28
+ body.style.top = prev.top;
29
+ body.style.width = prev.width;
30
+ body.style.overflowY = prev.overflowY;
31
+ window.scrollTo(0, scrollY);
32
+ };
33
+ }, [locked]);
34
+ }
35
+ //# sourceMappingURL=useScrollLock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useScrollLock.js","sourceRoot":"","sources":["../../src/scroll/useScrollLock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEnC;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,MAAe;IAC3C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,SAAS;YAAE,OAAO;QACvB,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;QAC1B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAE/B,MAAM,IAAI,GAAG;YACX,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ;YAC7B,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG;YACnB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK;YACvB,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS;SAChC,CAAC;QAEF,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC;QAC9B,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,OAAO,IAAI,CAAC;QACjC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC;QAC1B,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,QAAQ,CAAC;QAEhC,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;YACpC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;YAC1B,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YAC9B,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;YACtC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QAC9B,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,12 @@
1
+ export type Insets = {
2
+ top: number;
3
+ right: number;
4
+ bottom: number;
5
+ left: number;
6
+ };
7
+ export type KeyboardState = {
8
+ isOpen: boolean;
9
+ height: number;
10
+ source: "visualViewport" | "fallback";
11
+ };
12
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAElF,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IAEf,MAAM,EAAE,gBAAgB,GAAG,UAAU,CAAC;CACvC,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Sets:
3
+ * --ttt-vh: 1% of *layout* viewport height (window.innerHeight)
4
+ * --ttt-dvh: 1% of *visual* viewport height (visualViewport.height when available)
5
+ *
6
+ * Use in CSS:
7
+ * height: calc(var(--ttt-dvh, var(--ttt-vh, 1vh)) * 100);
8
+ */
9
+ export declare function useViewportHeightVars(): void;
10
+ //# sourceMappingURL=useViewportHeightVars.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useViewportHeightVars.d.ts","sourceRoot":"","sources":["../../src/viewport/useViewportHeightVars.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,SAoBpC"}