One Logo Pool Ball
wwwwwwwwwwwwwwwwwww

Text Input

Native text input with shared state, plus adaptive layout

useNativeState creates one observable handle shared between JavaScript and the bound native views. Pass the handle as value to One.UI.TextInput: keystrokes land in every bound view without a React render. The ref carries focus, blur, clear, isFocused, and setSelection.

import { One, useNativeState } from 'one'
function NameField() {
const name = useNativeState('')
return (
<One.UI.TextInput
value={name}
placeholder="Name"
onSubmitEditing={(text) => save(text)}
/>
)
}

One.UI.TextInput props mirror the familiar text input contract. value takes a native state handle (or is left uncontrolled with defaultValue); onChangeText reports edits; editable and readOnly gate input; multiline scrolls inside the field height on native (default 56) while web grows; maxLength clamps in host on Android and web and converges on the controlled round-trip on iOS; secureTextEntry obscures input; keyboardType and inputMode pick the keyboard; autoCapitalize, autoCorrect, and autoComplete tune corrections (autoComplete runs on iOS and web and is ignored on Android); returnKeyType and enterKeyHint name the return key; textAlign runs on Android and web and is ignored on iOS; autoFocus focuses on mount. Events are onFocus, onBlur, and onSubmitEditing, which receives the text. The web-only props (numberOfLines, rows, onContentSizeChange, onSelectionChange, selection, selectTextOnFocus, selectionColor, selectionHandleColor, cursorColor, caretHidden, placeholderTextColor, textStyle) apply on web and are accepted but ignored on native.

One.UI.SafeArea is documented under SafeAreaView.

Adaptive layout

useSizeClass() returns the window’s horizontal and vertical size classes (compact, regular, or unspecified) and re-renders when they change. On iOS they are the window scene’s UIUserInterfaceSizeClass values, so a layout can branch on the trait iOS uses rather than on the screen’s width. On a foldable such as iPhone Duo the outer display is compact and the inner display regular in both axes. On Android they come from the activity window’s WindowMetrics: width below 600dp is compact, otherwise regular; height below 480dp is compact, otherwise regular. They update on configuration and window-metrics changes.

useHinge() reports the hinge’s status (closed, partiallyOpen, fullyOpen, or unknown) and angle in radians, and onHingeChange subscribes outside React. The get* variants read the current value once. The first render already has the current hinge, so a hinge-keyed layout does not render its no-hinge branch first. On iOS the state comes from UIHinge. On Android the status comes from the Jetpack FoldingFeature (FLAT is fullyOpen, HALF_OPENED is partiallyOpen) and the angle from the hinge sensor; a hinge sensor with no folding feature in the current window reads closed only on an official 0° sensor reading and unknown otherwise, preserving the sensor angle; a device with no hinge reads null.

Safe area insets say how far to pull content in from each edge; they cannot describe a fold across the middle of the screen or a camera on the inner display. One.UI.ReservedRegions.Provider is a view that reports the regions reserved inside its own bounds, and useReservedRegions() reads them from the nearest provider. A division is a fold that content should not straddle; an occlusion is a camera cutout or system control that hides content. Each region has an id, a frame in the provider’s points (margins included), the margins kept around it for interactive content, and isActive. useReservedRegions() returns active regions unless you pass { includeInactive: true }, and { kind: 'division' } narrows to one kind. useReservedRegionsReady() turns true once the provider has taken its first reading, which lands before the first frame.

useWindowSegments() returns the unobstructed parts of the provider when an active full-span division separates it. useSpanning() reports whether that division splits the provider. The provider must fill the window to read window segments.

On iOS 27.1 the regions come from UIKit’s reservedRegions and update as the hinge moves. On Android a fold from Jetpack WindowManager is a division, active while it separates the display, and each display cutout is an occlusion; Android reports no margins. The web reports none.

import { One, useReservedRegions } from 'one'
function Canvas() {
const [fold] = useReservedRegions({ kind: 'division' })
if (!fold) return <Board />
return (
<>
<Board style={{ height: fold.frame.y }} />
<Palette style={{ top: fold.frame.y + fold.frame.height }} />
</>
)
}
<One.UI.ReservedRegions.Provider style={{ flex: 1 }}>
<Canvas />
</One.UI.ReservedRegions.Provider>

One.iOS.ArrangementView uses SwiftUI’s ArrangementView on iOS 27.1 or later. It accepts primary and secondary panes, with automatic, split, and overlay styles. With splitArrangementLayoutRatio={0.5} on a closed iPhone Duo, the first two styles stack equal panes; overlay gives both panes the full arrangement frame. Open and folded Duo postures have not yet been verified in One’s simulator fixture.

import { One, useSizeClass } from 'one'
function Workspace() {
const sizeClass = useSizeClass()
if (sizeClass.horizontal !== 'regular') return <Chat />
return (
<One.iOS.ArrangementView
style={{ flex: 1 }}
arrangementViewStyle="split"
splitArrangementLayoutRatio={0.5}
primary={<Chat />}
secondary={<Preview />}
/>
)
}

Edit this page on GitHub.