Skip to content
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,6 @@ coverage
.claude/*.md

# context files (session notes, etc.)
context/
context/
.omc/
.omx/
7 changes: 5 additions & 2 deletions .scripts/commands/generateDocs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 } = {};
const subCtx: { docSource?: string; translatedDoc?: string | null } = {};
tasks.add([
{
title: `Generate documents: ${sourceFilePath}`,
task: async (_, task) =>
task.newListr<{ docSource?: string; translatedDoc?: string }>(
task.newListr<{ docSource?: string; translatedDoc?: string | null }>(
[
{
title: `Convert JSDoc to markdown`,
Expand Down Expand Up @@ -147,6 +147,9 @@ function parseJSDoc(source: string) {
: (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') ?? '');

return {
Expand Down
18 changes: 16 additions & 2 deletions .scripts/commands/generateDocs/translate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,23 @@ ${origin}
`;

const response = await client.chat.completions.create({
model: 'gpt-3.5-turbo',
model: 'gpt-5.6-terra',
messages: [{ role: 'user', content: prompt }],
response_format: { type: 'json_object' },
// gpt-5.6-terra's endpoint compatibility lists structured_outputs but not the
// legacy json_object mode, so declare the shape via json_schema
response_format: {
type: 'json_schema',
json_schema: {
name: 'translation',
strict: true,
schema: {
type: 'object',
properties: { result: { type: 'string' } },
required: ['result'],
additionalProperties: false,
},
},
},
});

const translatedItem = response.choices[0].message.content;
Expand Down
53 changes: 11 additions & 42 deletions packages/mobile/src/hooks/useAvoidKeyboard/useAvoidKeyboard.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# useAvoidKeyboard

A React hook that helps fixed-bottom elements smoothly avoid the on-screen keyboard. When the keyboard appears, it moves the element upward using `transform` with a smooth transition.
`useAvoidKeyboard` is a React hook that helps fixed-bottom elements avoid the on-screen keyboard. It returns a CSS style that can be applied to `position: fixed` elements to smoothly move them above the keyboard when it appears.

## Interface

```ts
function useAvoidKeyboard(
options?: UseAvoidKeyboardOptions
options: UseAvoidKeyboardOptions
): UseAvoidKeyboardResult;
```

Expand All @@ -15,37 +15,35 @@ function useAvoidKeyboard(
<Interface
name="options"
type="UseAvoidKeyboardOptions"
description="Options to configure the keyboard avoidance behavior."
description="Configuration options."
:nested="[
{
name: 'options.safeAreaBottom',
type: 'number',
required: false,
defaultValue: '0',
description:
'Base bottom offset in pixels when the keyboard is hidden. Useful for accounting for the iPhone home indicator area.',
description: 'Base bottom offset in pixels when keyboard is hidden.',
},
{
name: 'options.transitionDuration',
type: 'number',
required: false,
defaultValue: '200',
description:
'Transition duration in milliseconds for smooth animation.',
description: 'Transition duration in milliseconds for smooth animation.',
},
{
name: 'options.transitionTimingFunction',
type: 'string',
type: 'CSSProperties[\'transitionTimingFunction\']',
required: false,
description:
'Transition timing function for the animation. Defaults to <code>ease-out</code>.',
defaultValue: '\'ease-out\'',
description: 'Transition timing function for the animation.',
},
{
name: 'options.immediate',
type: 'boolean',
required: false,
description:
'If <code>true</code>, gets the current keyboard height immediately on mount. Defaults to <code>true</code>.',
defaultValue: 'true',
description: 'If true, gets the initial keyboard height on mount.',
},
]"
/>
Expand All @@ -55,15 +53,7 @@ function useAvoidKeyboard(
<Interface
name=""
type="UseAvoidKeyboardResult"
description="An object containing the CSS style for keyboard avoidance."
:nested="[
{
name: 'style',
type: 'CSSProperties',
description:
'CSS style object to apply to the fixed-bottom element. Contains <code>transform</code> and <code>transition</code> properties.',
},
]"
description="object containing the <code>style</code> property to apply to the fixed bottom element."
/>

## Example
Expand All @@ -87,24 +77,3 @@ function FixedBottomCTA() {
);
}
```

```tsx
// 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 @@ -49,7 +49,6 @@ type UseAvoidKeyboardResult = {
* @returns {UseAvoidKeyboardResult} An object containing the `style` property to apply to the fixed bottom element.
*
* @example
* ```tsx
* function FixedBottomCTA() {
* const { style } = useAvoidKeyboard();
*
Expand All @@ -67,10 +66,8 @@ type UseAvoidKeyboardResult = {
* </div>
* );
* }
* ```
*
* @example
* ```tsx
* // With safe area bottom offset (e.g., for iPhone home indicator)
* function FixedBottomCTA() {
* const { style } = useAvoidKeyboard({ safeAreaBottom: 34 });
Expand All @@ -89,7 +86,6 @@ type UseAvoidKeyboardResult = {
* </div>
* );
* }
* ```
*/
export function useAvoidKeyboard(options: UseAvoidKeyboardOptions = {}): UseAvoidKeyboardResult {
const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,19 @@ import { disableBodyScrollLock } from '../../utils/disableBodyScrollLock/index.t
import { enableBodyScrollLock } from '../../utils/enableBodyScrollLock/index.ts';

/**
* Hook to lock body scroll
*
* Automatically locks body scroll when mounted, unlocks when unmounted.
* @description
* `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.
*
* @example
* ```tsx
* function Modal() {
* useBodyScrollLock();
* return <div className="modal">Modal content</div>;
* }
* ```
*
* @example
* ```tsx
* // Multiple modals - single lock pattern
* function BodyScrollLock() {
* useBodyScrollLock();
Expand All @@ -37,7 +34,6 @@ import { enableBodyScrollLock } from '../../utils/enableBodyScrollLock/index.ts'
* </>
* );
* }
* ```
*/
export function useBodyScrollLock(): void {
useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# useKeyboardHeight

A React hook that tracks the on-screen keyboard height in real time. It automatically updates when the keyboard appears, disappears, or changes size.
`useKeyboardHeight` is a React hook that tracks the on-screen keyboard height. It returns the current keyboard height in pixels, which updates automatically when the keyboard appears, disappears, or changes size.

## Interface

```ts
function useKeyboardHeight(
options?: UseKeyboardHeightOptions
options: UseKeyboardHeightOptions
): UseKeyboardHeightResult;
```

Expand All @@ -15,15 +15,14 @@ function useKeyboardHeight(
<Interface
name="options"
type="UseKeyboardHeightOptions"
description="Options to configure the keyboard height tracking behavior."
description="Configuration options."
:nested="[
{
name: 'options.immediate',
type: 'boolean',
required: false,
defaultValue: 'true',
description:
'If <code>true</code>, gets the current keyboard height immediately on mount.',
description: 'If true, gets the initial keyboard height on mount.',
},
]"
/>
Expand All @@ -33,15 +32,7 @@ function useKeyboardHeight(
<Interface
name=""
type="UseKeyboardHeightResult"
description="An object containing the keyboard height information."
:nested="[
{
name: 'keyboardHeight',
type: 'number',
description:
'The current keyboard height in pixels. Returns <code>0</code> when the keyboard is closed.',
},
]"
description="object containing the current keyboard height in pixels."
/>

## Example
Expand All @@ -57,17 +48,3 @@ function ChatInput() {
);
}
```

```tsx
function KeyboardStatus() {
const { keyboardHeight } = useKeyboardHeight();

return (
<div>
{keyboardHeight > 0
? `Keyboard is open (${keyboardHeight}px)`
: 'Keyboard is closed'}
</div>
);
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ type UseKeyboardHeightResult = {
* @returns {UseKeyboardHeightResult} An object containing the current keyboard height in pixels.
*
* @example
* ```tsx
* function ChatInput() {
* const { keyboardHeight } = useKeyboardHeight();
*
Expand All @@ -39,7 +38,6 @@ type UseKeyboardHeightResult = {
* </div>
* );
* }
* ```
*/
export function useKeyboardHeight(options: UseKeyboardHeightOptions = {}): UseKeyboardHeightResult {
const { immediate = true } = options;
Expand Down
10 changes: 3 additions & 7 deletions packages/mobile/src/hooks/useNetworkStatus/useNetworkStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ type NavigatorWithConnection = {
} & Navigator;

/**
* React hook to access Network Information API
*
* Provides raw network connection data. Returns undefined for all properties
* @description
* `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**:
Expand All @@ -73,7 +73,6 @@ type NavigatorWithConnection = {
* - `saveData` - User's data saver preference
*
* @example
* ```tsx
* function AdaptiveImage() {
* const { effectiveType, saveData } = useNetworkStatus();
*
Expand All @@ -87,10 +86,8 @@ type NavigatorWithConnection = {
* />
* );
* }
* ```
*
* @example
* ```tsx
* function VideoPlayer() {
* const { type, downlink } = useNetworkStatus();
*
Expand All @@ -99,7 +96,6 @@ type NavigatorWithConnection = {
*
* return <video src="video.mp4" autoPlay={shouldAutoplay} />;
* }
* ```
*
* @see https://wicg.github.io/netinfo/
* @see https://developer.mozilla.org/en-US/docs/Web/API/Network_Information_API
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ export type PageVisibility = {
};

/**
* React hook to detect page visibility changes
*
* Monitors when the user switches tabs or minimizes the browser using the Page Visibility API.
* @description
* `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.
Expand All @@ -31,7 +31,6 @@ export type PageVisibility = {
* - `visibilityState` - Current visibility state: 'visible' | 'hidden'
*
* @example
* ```tsx
* function VideoPlayer() {
* const { isVisible } = usePageVisibility();
* const videoRef = useRef<HTMLVideoElement>(null);
Expand All @@ -47,10 +46,8 @@ export type PageVisibility = {
*
* return <video ref={videoRef} src="video.mp4" />;
* }
* ```
*
* @example
* ```tsx
* function Analytics() {
* const { isVisible, visibilityState } = usePageVisibility();
*
Expand All @@ -63,7 +60,6 @@ export type PageVisibility = {
*
* return null;
* }
* ```
*/
export function usePageVisibility(): PageVisibility {
const [pageVisibility, setPageVisibility] = useState<PageVisibility>(() => getPageVisibility());
Expand Down
Loading
Loading