Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 28 additions & 23 deletions .scripts/commands/generateDocs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,27 @@ 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`,
task: async ctx => {
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;
}
},
},
{
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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,
Expand Down
33 changes: 31 additions & 2 deletions packages/mobile/src/hooks/useAvoidKeyboard/useAvoidKeyboard.md
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -53,7 +54,16 @@ function useAvoidKeyboard(
<Interface
name=""
type="UseAvoidKeyboardResult"
description="object containing the <code>style</code> property to apply to the fixed bottom element."
description="object containing the CSS style for keyboard avoidance."
:nested="[
{
name: 'style',
type: 'CSSProperties',
required: false,
description:
'CSS style object to apply to the fixed bottom element. Contains <code>transform</code> and <code>transition</code> properties.',
},
]"
/>

## Example
Expand All @@ -76,4 +86,23 @@ function FixedBottomCTA() {
</div>
);
}

// With safe area bottom offset (e.g., for iPhone home indicator)
function FixedBottomCTA() {
const { style } = useAvoidKeyboard({ safeAreaBottom: 34 });

return (
<div
style={{
position: 'fixed',
bottom: 0,
left: 0,
right: 0,
...style,
}}
>
<button>Submit</button>
</div>
);
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,16 @@ function useKeyboardHeight(
<Interface
name=""
type="UseKeyboardHeightResult"
description="object containing the current keyboard height in pixels."
description="object containing the current keyboard height."
:nested="[
{
name: 'keyboardHeight',
type: 'number',
required: false,
description:
'The current keyboard height in pixels. 0 when the keyboard is hidden.',
},
]"
/>

## Example
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down
20 changes: 7 additions & 13 deletions packages/mobile/src/hooks/useSafeAreaInset/useSafeAreaInset.md
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -16,36 +10,38 @@ function useSafeAreaInset(): SafeAreaInset;

### Parameters

This hook does not accept any parameters.

### Return Value

<Interface
name=""
type="SafeAreaInset"
description="An object containing safe area insets for all four sides."
description="object containing safe area insets for all four sides."
:nested="[
{
name: 'top',
type: 'number',
required: false,
description:
'Top safe area inset in pixels. Accounts for the notch, Dynamic Island, or status bar.',
},
{
name: 'bottom',
type: 'number',
required: false,
description:
'Bottom safe area inset in pixels. Accounts for the home indicator on Face ID devices.',
},
{
name: 'left',
type: 'number',
required: false,
description:
'Left safe area inset in pixels. Accounts for rounded corners in landscape mode.',
},
{
name: 'right',
type: 'number',
required: false,
description:
'Right safe area inset in pixels. Accounts for rounded corners in landscape mode.',
},
Expand All @@ -55,7 +51,7 @@ This hook does not accept any parameters.
## Example

```tsx
function SafeLayout() {
function MyComponent() {
const safeArea = useSafeAreaInset();

return (
Expand All @@ -71,9 +67,7 @@ function SafeLayout() {
</div>
);
}
```

```tsx
// Automatically updates when screen rotates
function RotationAwareHeader() {
const { top, left, right } = useSafeAreaInset();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
@@ -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

<Interface
required
name="options.throttleMs"
type=""
description="Throttle interval (default: 50ms)"
name="options"
type="UseScrollDirectionOptions"
description="Configuration options."
:nested="[
{
name: 'options.throttleMs',
type: 'number',
required: false,
defaultValue: '50',
description: 'Throttle interval in milliseconds.',
},
]"
/>

### Return Value

<Interface
name=""
type=""
description="direction state (direction: \'up\' | \'down\' | null, position: number)"
type="ScrollDirectionState"
description="direction state: <code>direction</code> (<code>\'up\' | \'down\' | null</code>) and <code>position</code> (px)."
/>

## Example
Expand Down
Loading
Loading