From 41fcdac48485fecbfe81d8878eaa9145d35d7360 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 10 Aug 2026 10:49:20 +0000
Subject: [PATCH 1/3] Generate docs for
useAvoidKeyboard,useBodyScrollLock,useKeyboardHeight,useNetworkStatus,usePageVisibility,useSafeAreaInset,useScrollDirection,useVisualViewport
---
.../useBodyScrollLock/useBodyScrollLock.md | 2 +
.../useNetworkStatus/useNetworkStatus.md | 2 +
.../usePageVisibility/usePageVisibility.md | 2 +
.../useSafeAreaInset/useSafeAreaInset.md | 59 +---------------
.../useScrollDirection/useScrollDirection.md | 26 +++++--
.../useVisualViewport/useVisualViewport.md | 69 ++-----------------
6 files changed, 32 insertions(+), 128 deletions(-)
diff --git a/packages/mobile/src/hooks/useBodyScrollLock/useBodyScrollLock.md b/packages/mobile/src/hooks/useBodyScrollLock/useBodyScrollLock.md
index 53f0f3e7..5198e17d 100644
--- a/packages/mobile/src/hooks/useBodyScrollLock/useBodyScrollLock.md
+++ b/packages/mobile/src/hooks/useBodyScrollLock/useBodyScrollLock.md
@@ -1,5 +1,7 @@
# useBodyScrollLock
+`useBodyScrollLock` is a React hook that locks body scroll while the component is mounted. It automatically locks on mount and unlocks on unmount. **Note:** For multiple overlapping modals, use a single lock at the parent level.
+
## Interface
```ts
diff --git a/packages/mobile/src/hooks/useNetworkStatus/useNetworkStatus.md b/packages/mobile/src/hooks/useNetworkStatus/useNetworkStatus.md
index 1db1650c..14fcedc4 100644
--- a/packages/mobile/src/hooks/useNetworkStatus/useNetworkStatus.md
+++ b/packages/mobile/src/hooks/useNetworkStatus/useNetworkStatus.md
@@ -1,5 +1,7 @@
# useNetworkStatus
+`useNetworkStatus` is a React hook that provides access to the Network Information API. It provides raw network connection data. Returns undefined for all properties if the API is not supported (e.g., Safari, Firefox). **Browser Support**: - Chrome/Edge (Android): Full support - Chrome/Edge (Desktop): Partial support (effectiveType, downlink, rtt, saveData) - Firefox: Not supported - Safari: Not supported
+
## Interface
```ts
diff --git a/packages/mobile/src/hooks/usePageVisibility/usePageVisibility.md b/packages/mobile/src/hooks/usePageVisibility/usePageVisibility.md
index 637ac8e4..b01eb0cc 100644
--- a/packages/mobile/src/hooks/usePageVisibility/usePageVisibility.md
+++ b/packages/mobile/src/hooks/usePageVisibility/usePageVisibility.md
@@ -1,5 +1,7 @@
# usePageVisibility
+`usePageVisibility` is a React hook that detects page visibility changes. It monitors when the user switches tabs or minimizes the browser using the Page Visibility API. Useful for pausing/resuming animations, videos, or background tasks. **SSR Behavior**: Returns `{ isVisible: true, visibilityState: 'visible' }` during server-side rendering.
+
## Interface
```ts
diff --git a/packages/mobile/src/hooks/useSafeAreaInset/useSafeAreaInset.md b/packages/mobile/src/hooks/useSafeAreaInset/useSafeAreaInset.md
index 498649e7..600bce35 100644
--- a/packages/mobile/src/hooks/useSafeAreaInset/useSafeAreaInset.md
+++ b/packages/mobile/src/hooks/useSafeAreaInset/useSafeAreaInset.md
@@ -1,12 +1,6 @@
# useSafeAreaInset
-A React hook that tracks device safe area insets in real time. It automatically updates when the screen orientation changes (e.g., portrait to landscape).
-
-Safe area insets account for device-specific UI elements:
-
-- **top**: Notch, Dynamic Island, or status bar
-- **bottom**: Home indicator on Face ID devices
-- **left/right**: Rounded corners in landscape mode
+`useSafeAreaInset` is a React hook that tracks safe area inset changes. It returns the safe area insets that automatically update when the screen orientation changes (e.g., portrait to landscape). Safe area insets account for device-specific UI elements: - **top**: Notch, Dynamic Island, or status bar - **bottom**: Home indicator on Face ID devices - **left/right**: Rounded corners in landscape mode
## Interface
@@ -16,46 +10,18 @@ function useSafeAreaInset(): SafeAreaInset;
### Parameters
-This hook does not accept any parameters.
-
### Return Value
## Example
```tsx
-function SafeLayout() {
+function MyComponent() {
const safeArea = useSafeAreaInset();
return (
@@ -72,22 +38,3 @@ function SafeLayout() {
);
}
```
-
-```tsx
-// Automatically updates when screen rotates
-function RotationAwareHeader() {
- const { top, left, right } = useSafeAreaInset();
-
- return (
-
- Header content
-
- );
-}
-```
diff --git a/packages/mobile/src/hooks/useScrollDirection/useScrollDirection.md b/packages/mobile/src/hooks/useScrollDirection/useScrollDirection.md
index 80dbb18f..b0f9900c 100644
--- a/packages/mobile/src/hooks/useScrollDirection/useScrollDirection.md
+++ b/packages/mobile/src/hooks/useScrollDirection/useScrollDirection.md
@@ -1,26 +1,38 @@
# useScrollDirection
+`useScrollDirection` is a React hook that detects scroll direction. It returns scroll direction (up/down) and current scroll position. Throttled by default (50ms) for performance.
+
## Interface
```ts
-function useScrollDirection(): void;
+function useScrollDirection(
+ options: UseScrollDirectionOptions
+): ScrollDirectionState;
```
### Parameters
### Return Value
## Example
diff --git a/packages/mobile/src/hooks/useVisualViewport/useVisualViewport.md b/packages/mobile/src/hooks/useVisualViewport/useVisualViewport.md
index b3df5c83..7734794c 100644
--- a/packages/mobile/src/hooks/useVisualViewport/useVisualViewport.md
+++ b/packages/mobile/src/hooks/useVisualViewport/useVisualViewport.md
@@ -1,8 +1,6 @@
# useVisualViewport
-React hook to track Visual Viewport changes.
-
-Returns the actual visible area in mobile WebView, which changes when the keyboard appears or the user zooms/scrolls.
+`useVisualViewport` is a React hook that tracks Visual Viewport changes. It returns the actual visible area in mobile WebView, which changes when the keyboard appears or the user zooms/scrolls. **Important:** `viewport` is `null` on SSR or in browsers that don't support Visual Viewport API. Always check for null before accessing viewport properties. **Tip:** If you only need keyboard height, use `useKeyboardHeight()` instead for a simpler API.
## Interface
@@ -12,46 +10,12 @@ function useVisualViewport(): { viewport: VisualViewportState | null };
### Parameters
-This hook takes no parameters.
-
### Return Value
## Example
@@ -78,28 +42,3 @@ function CustomLayout() {
);
}
```
-
-### Detecting Zoom
-
-```tsx
-const { viewport } = useVisualViewport();
-if (viewport && viewport.scale > 1.3) {
- // Hide floating UI when user zooms in
- setShowFloatingButton(false);
-}
-```
-
-## Notes
-
-- **SSR Safety**: `viewport` is `null` on SSR or in browsers that don't support Visual Viewport API. Always check for null before accessing viewport properties.
-- **Browser Support**: Visual Viewport API is supported in modern mobile browsers. For unsupported environments, the hook returns `null`.
-- **Performance**: Uses React's `startTransition` to prevent blocking updates during viewport changes.
-- **Simpler Alternative**: If you only need keyboard height, use `useKeyboardHeight()` instead for a simpler API.
-- **Platform Differences**:
- - iOS: `offsetTop` becomes negative when keyboard appears
- - Android: `offsetTop` typically remains 0
-- **Use Cases**:
- - Detecting keyboard appearance
- - Responding to pinch-zoom gestures
- - Creating viewport-aware layouts
- - Hiding/showing UI elements based on zoom level
From 911b494d4ab972eaebd880ce5a106787c7f2511e Mon Sep 17 00:00:00 2001
From: hyesung oh
Date: Mon, 10 Aug 2026 20:03:29 +0900
Subject: [PATCH 2/3] fix(scripts): repair always-true translation skip check
and collect all @example tags
---
.scripts/commands/generateDocs/index.ts | 51 ++++++++++++++-----------
1 file changed, 28 insertions(+), 23 deletions(-)
diff --git a/.scripts/commands/generateDocs/index.ts b/.scripts/commands/generateDocs/index.ts
index c933e5cb..2710d5e5 100644
--- a/.scripts/commands/generateDocs/index.ts
+++ b/.scripts/commands/generateDocs/index.ts
@@ -25,12 +25,12 @@ export async function generateDocs(names: string[]) {
names
.map(name => [name, glob.sync(`**/${name}.ts*`, { cwd: getRootPath() })[0]])
.forEach(([name, sourceFilePath]) => {
- const subCtx: { docSource?: string; translatedDoc?: string | null } = {};
+ const subCtx: { docSource?: string; previousDocSource?: string | null; translatedDoc?: string | null } = {};
tasks.add([
{
title: `Generate documents: ${sourceFilePath}`,
task: async (_, task) =>
- task.newListr<{ docSource?: string; translatedDoc?: string | null }>(
+ task.newListr<{ docSource?: string; previousDocSource?: string | null; translatedDoc?: string | null }>(
[
{
title: `Convert JSDoc to markdown`,
@@ -38,6 +38,14 @@ export async function generateDocs(names: string[]) {
const docSource = await jsdocToMd(name, parseJSDoc(await fs.readFile(sourceFilePath, 'utf-8')));
ctx.docSource = docSource;
+
+ // captured before "Write English" overwrites the file on disk; reading it at
+ // translate time would always compare equal and skip the translation
+ try {
+ ctx.previousDocSource = await fs.readFile(`${path.dirname(sourceFilePath)}/${name}.md`, 'utf-8');
+ } catch {
+ ctx.previousDocSource = null;
+ }
},
},
{
@@ -66,15 +74,8 @@ export async function generateDocs(names: string[]) {
}
// Skip if Korean file already exists and English file hasn't changed
- if (isFileExists) {
- try {
- const existingEnglish = await fs.readFile(`${dirname}/${name}.md`, 'utf-8');
- if (existingEnglish === docSource) {
- return;
- }
- } catch {
- // Continue with translation if we can't read existing file
- }
+ if (isFileExists && ctx.previousDocSource === docSource) {
+ return;
}
if (docSource == null) {
@@ -139,18 +140,22 @@ function parseJSDoc(source: string) {
const nestedValueOfReturns = returns.length === 0 ? undefined : getNestedValuesFromReturn(returns[0]);
- const exampleSource = targetComment.tags.find(tag => tag.tag === 'example')?.source;
-
- const example =
- exampleSource == null
- ? ''
- : (exampleSource
- .splice(1, exampleSource.length - 2)
- .map(line => line.source.replace(/\s\*\s{0,1}/, ''))
- // the doc template wraps the example in its own ```tsx fence, so fences
- // inside @example would nest and render as literal backticks
- .filter(line => !/^\s*```/.test(line))
- .join('\n') ?? '');
+ const example = targetComment.tags
+ .filter(tag => tag.tag === 'example')
+ .map(tag =>
+ tag.source
+ .map(line => line.source.replace(/\s\*\s{0,1}/, ''))
+ // fence lines are dropped because the doc template wraps the example in its
+ // own ```tsx fence; nested fences would render as literal backticks
+ .filter(line => {
+ const trimmed = line.trim();
+ return trimmed !== '@example' && trimmed !== '/' && !/^\s*```/.test(line);
+ })
+ .join('\n')
+ .trim()
+ )
+ .filter(text => text.length > 0)
+ .join('\n\n');
return {
description,
From 6bd43dcc3ab776ffcea15d99768c98a6d3f0c809 Mon Sep 17 00:00:00 2001
From: hyesung oh
Date: Mon, 10 Aug 2026 20:03:29 +0900
Subject: [PATCH 3/3] docs(mobile): restore nested return docs and second
example lost in regeneration
---
.../useAvoidKeyboard/useAvoidKeyboard.md | 33 ++++++++++++-
.../useAvoidKeyboard/useAvoidKeyboard.ts | 5 +-
.../useKeyboardHeight/useKeyboardHeight.md | 11 ++++-
.../useKeyboardHeight/useKeyboardHeight.ts | 3 +-
.../useSafeAreaInset/useSafeAreaInset.md | 49 ++++++++++++++++++-
.../useSafeAreaInset/useSafeAreaInset.ts | 6 ++-
.../useVisualViewport/useVisualViewport.md | 44 ++++++++++++++++-
.../useVisualViewport/useVisualViewport.ts | 8 ++-
8 files changed, 149 insertions(+), 10 deletions(-)
diff --git a/packages/mobile/src/hooks/useAvoidKeyboard/useAvoidKeyboard.md b/packages/mobile/src/hooks/useAvoidKeyboard/useAvoidKeyboard.md
index b3c3d4a4..0c8b9f44 100644
--- a/packages/mobile/src/hooks/useAvoidKeyboard/useAvoidKeyboard.md
+++ b/packages/mobile/src/hooks/useAvoidKeyboard/useAvoidKeyboard.md
@@ -22,7 +22,8 @@ function useAvoidKeyboard(
type: 'number',
required: false,
defaultValue: '0',
- description: 'Base bottom offset in pixels when keyboard is hidden.',
+ description:
+ 'Base bottom offset in pixels when the keyboard is hidden. Useful for accounting for the iPhone home indicator area.',
},
{
name: 'options.transitionDuration',
@@ -53,7 +54,16 @@ function useAvoidKeyboard(
## Example
@@ -76,4 +86,23 @@ function FixedBottomCTA() {
);
}
+
+// With safe area bottom offset (e.g., for iPhone home indicator)
+function FixedBottomCTA() {
+ const { style } = useAvoidKeyboard({ safeAreaBottom: 34 });
+
+ return (
+
+
+
+ );
+}
```
diff --git a/packages/mobile/src/hooks/useAvoidKeyboard/useAvoidKeyboard.ts b/packages/mobile/src/hooks/useAvoidKeyboard/useAvoidKeyboard.ts
index c4e52736..bb9d8736 100644
--- a/packages/mobile/src/hooks/useAvoidKeyboard/useAvoidKeyboard.ts
+++ b/packages/mobile/src/hooks/useAvoidKeyboard/useAvoidKeyboard.ts
@@ -41,12 +41,13 @@ type UseAvoidKeyboardResult = {
* to smoothly move them above the keyboard when it appears.
*
* @param {UseAvoidKeyboardOptions} [options] - Configuration options.
- * @param {number} [options.safeAreaBottom=0] - Base bottom offset in pixels when keyboard is hidden.
+ * @param {number} [options.safeAreaBottom=0] - Base bottom offset in pixels when the keyboard is hidden. Useful for accounting for the iPhone home indicator area.
* @param {number} [options.transitionDuration=200] - Transition duration in milliseconds for smooth animation.
* @param {CSSProperties['transitionTimingFunction']} [options.transitionTimingFunction='ease-out'] - Transition timing function for the animation.
* @param {boolean} [options.immediate=true] - If true, gets the initial keyboard height on mount.
*
- * @returns {UseAvoidKeyboardResult} An object containing the `style` property to apply to the fixed bottom element.
+ * @returns {UseAvoidKeyboardResult} An object containing the CSS style for keyboard avoidance.
+ * - style `CSSProperties` - CSS style object to apply to the fixed bottom element. Contains `transform` and `transition` properties;
*
* @example
* function FixedBottomCTA() {
diff --git a/packages/mobile/src/hooks/useKeyboardHeight/useKeyboardHeight.md b/packages/mobile/src/hooks/useKeyboardHeight/useKeyboardHeight.md
index 68a94597..5bc65b97 100644
--- a/packages/mobile/src/hooks/useKeyboardHeight/useKeyboardHeight.md
+++ b/packages/mobile/src/hooks/useKeyboardHeight/useKeyboardHeight.md
@@ -32,7 +32,16 @@ function useKeyboardHeight(
## Example
diff --git a/packages/mobile/src/hooks/useKeyboardHeight/useKeyboardHeight.ts b/packages/mobile/src/hooks/useKeyboardHeight/useKeyboardHeight.ts
index 1763e0a5..8953ee99 100644
--- a/packages/mobile/src/hooks/useKeyboardHeight/useKeyboardHeight.ts
+++ b/packages/mobile/src/hooks/useKeyboardHeight/useKeyboardHeight.ts
@@ -26,7 +26,8 @@ type UseKeyboardHeightResult = {
* @param {UseKeyboardHeightOptions} [options] - Configuration options.
* @param {boolean} [options.immediate=true] - If true, gets the initial keyboard height on mount.
*
- * @returns {UseKeyboardHeightResult} An object containing the current keyboard height in pixels.
+ * @returns {UseKeyboardHeightResult} An object containing the current keyboard height.
+ * - keyboardHeight `number` - The current keyboard height in pixels. 0 when the keyboard is hidden;
*
* @example
* function ChatInput() {
diff --git a/packages/mobile/src/hooks/useSafeAreaInset/useSafeAreaInset.md b/packages/mobile/src/hooks/useSafeAreaInset/useSafeAreaInset.md
index 600bce35..1e15f100 100644
--- a/packages/mobile/src/hooks/useSafeAreaInset/useSafeAreaInset.md
+++ b/packages/mobile/src/hooks/useSafeAreaInset/useSafeAreaInset.md
@@ -15,7 +15,37 @@ function useSafeAreaInset(): SafeAreaInset;
## Example
@@ -37,4 +67,21 @@ function MyComponent() {
);
}
+
+// Automatically updates when screen rotates
+function RotationAwareHeader() {
+ const { top, left, right } = useSafeAreaInset();
+
+ return (
+
+ Header content
+
+ );
+}
```
diff --git a/packages/mobile/src/hooks/useSafeAreaInset/useSafeAreaInset.ts b/packages/mobile/src/hooks/useSafeAreaInset/useSafeAreaInset.ts
index be82fe59..1e93a531 100644
--- a/packages/mobile/src/hooks/useSafeAreaInset/useSafeAreaInset.ts
+++ b/packages/mobile/src/hooks/useSafeAreaInset/useSafeAreaInset.ts
@@ -14,7 +14,11 @@ import { isServer } from '../../utils/isServer/index.ts';
* - **bottom**: Home indicator on Face ID devices
* - **left/right**: Rounded corners in landscape mode
*
- * @returns {SafeAreaInset} Object containing safe area insets for all four sides.
+ * @returns {SafeAreaInset} An object containing safe area insets for all four sides.
+ * - top `number` - Top safe area inset in pixels. Accounts for the notch, Dynamic Island, or status bar;
+ * - bottom `number` - Bottom safe area inset in pixels. Accounts for the home indicator on Face ID devices;
+ * - left `number` - Left safe area inset in pixels. Accounts for rounded corners in landscape mode;
+ * - right `number` - Right safe area inset in pixels. Accounts for rounded corners in landscape mode;
*
* @example
* function MyComponent() {
diff --git a/packages/mobile/src/hooks/useVisualViewport/useVisualViewport.md b/packages/mobile/src/hooks/useVisualViewport/useVisualViewport.md
index 7734794c..a32b3f9e 100644
--- a/packages/mobile/src/hooks/useVisualViewport/useVisualViewport.md
+++ b/packages/mobile/src/hooks/useVisualViewport/useVisualViewport.md
@@ -15,7 +15,49 @@ function useVisualViewport(): { viewport: VisualViewportState | null };
## Example
diff --git a/packages/mobile/src/hooks/useVisualViewport/useVisualViewport.ts b/packages/mobile/src/hooks/useVisualViewport/useVisualViewport.ts
index 14208e16..bae5ae6d 100644
--- a/packages/mobile/src/hooks/useVisualViewport/useVisualViewport.ts
+++ b/packages/mobile/src/hooks/useVisualViewport/useVisualViewport.ts
@@ -53,7 +53,13 @@ type VisualViewportState = {
* **Tip:** If you only need keyboard height, use `useKeyboardHeight()` instead
* for a simpler API.
*
- * @returns {{ viewport: VisualViewportState | null }} Object containing Visual Viewport state, or `null` viewport if not supported.
+ * @returns {{ viewport: VisualViewportState | null }} An object containing the Visual Viewport state.
+ * - viewport `VisualViewportState | null` - Visual Viewport state object, or `null` if not supported (SSR or browsers without the Visual Viewport API);
+ * - viewport.width `number` - Viewport width in pixels;
+ * - viewport.height `number` - Viewport height in pixels;
+ * - viewport.offsetLeft `number` - Viewport left offset in pixels from the layout viewport. Typically 0 unless horizontal scrolling or panning occurs;
+ * - viewport.offsetTop `number` - Viewport top offset in pixels from the layout viewport. Becomes negative on iOS when the keyboard appears, so use `-offsetTop` for the keyboard height. Typically remains 0 on Android;
+ * - viewport.scale `number` - Pinch-zoom scaling factor. 1.0 means no zoom, greater than 1.0 means zoomed in;
*
* @see {@link useKeyboardHeight} - Simpler hook for keyboard height only
*