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,
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/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/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/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..1e15f100 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,36 +10,38 @@ function useSafeAreaInset(): SafeAreaInset;
### Parameters
-This hook does not accept any parameters.
-
### Return Value
### Return Value
## Example
diff --git a/packages/mobile/src/hooks/useVisualViewport/useVisualViewport.md b/packages/mobile/src/hooks/useVisualViewport/useVisualViewport.md
index b3df5c83..a32b3f9e 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,44 +10,52 @@ function useVisualViewport(): { viewport: VisualViewportState | null };
### Parameters
-This hook takes no parameters.
-
### Return Value
@@ -78,28 +84,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
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
*