You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Browse filesBrowse the repository at this point in the historyBrowse files
authored
Review cleanup: one value limit, dark mode, per-frame work, submitBehavior, packaging (#11)
* Rolling number: one value limit, dark mode, no per-frame allocations
The engine clamped the scaled magnitude at 10^15 for a jump and 10^17 for
a roll, so `jumpTo` and `animateTo` showed different digits above that;
both now share one limit, the stagger's longest delay is stored once per
roll, and the unused `revealFraction` is gone.
Both views follow a light/dark switch when no `color` is set: iOS
rasterizes the glyphs with the trait-resolved label color and rebuilds
them on a trait or display-scale change (the scale now comes from the
view's traits, not `UIScreen.main`), Android rebuilds its paints on a
configuration change. Per frame, iOS reuses its wheel and element
buffers, keys the glyph caches by a value type and compares layers in
place; Android pools its layout elements, splits the affixes once per
format and slides one cached shimmer gradient. Both format the
accessibility text only when a screen reader asks for it, and Android
reads the animator scale once behind a settings observer.
The wrapper keeps one `ref` handle per mount and tests the right-to-left
resolution; `lib/` ships ES module, CommonJS and declaration builds; the
Android Gradle plugin is pinned only for a standalone build, Java 17.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* Input: worklet ids on Android, dark mode on iOS, submitBehavior on multiline
Android never marked five worklet-id props dirty, so a changed handler
kept calling a dead id; they flush like the other three now. The view
also re-feeds after `secureTextEntry` or `morph` toggles, applies
`maxLength` only in text mode, sets tabular figures in every mode,
honours `showSoftInputOnFocus`, resolves its theme colours once and
again on a configuration change, and caches the animator scale.
iOS re-rasterizes glyphs and re-resolves frame, label and caret colours
on a trait or scale change (no more `UIScreen.main`), the Fabric
focus/blur commands find multiline fields, `maxIntegerDigits` allows 30
as on Android, a `morph` toggled back on re-feeds, and a frame no longer
allocates per glyph.
`submitBehavior` gains `'newline'`, resolved as `TextInput` resolves it,
and both platforms honour `submit` / `blurAndSubmit` on a multiline
field. The wrapper no longer re-renders on every keystroke of an
uncontrolled field, memoises `maskNotations` and the colours, exports
the missing types, drops affixes on multiline with a warning, and gains
43 tests; the README props table is complete and guarded by a test.
The native `affixAlign` prop is gone (the wrapper folds it), dead
engine, mask and worklet-bridge methods are removed, the outline
geometry writes into a reused buffer, and packaging mirrors the rolling
number's dual build with `react-native-worklets` as an optional peer.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* Repo: build step in CI, wasm rebuilt on deploy, the Nitro patch documented
The docs workflow rebuilds both engines to WebAssembly before deploying,
since a change under cpp/ used to trigger a deploy with a stale build
(the committed builds are refreshed here too, and the rolling engine's
script links with em++). The package workflow builds `lib/`.
The README's test command was `bun test`, which runs Bun's own runner
against the Jest files; it is `bun run test`. It also documents the
Android view-props patch for Nitro 0.37 that consumers need until the
upstream fix ships. The demo gains a multiline field with a
`submitBehavior` toggle, the row the device check of that feature used.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
---------
Co-authored-by: Ronald Goedeke <ronald@margelo.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: README.md
+7-2Lines changed: 7 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -114,8 +114,9 @@ import { NitroInput } from 'react-native-nitro-input'
114
114
```sh
115
115
bun install # hoisted linker, see bunfig.toml
116
116
bun specs # re-run nitrogen after editing src/specs/*.nitro.ts
117
-
bun test# jest tests for the JS wrapper
118
-
bun --cwd packages/react-native-nitro-rolling-number run test:cpp # engine tests (same for packages/react-native-nitro-input)
117
+
bun run test# jest tests for the JS wrappers (plain `bun test` would run Bun's own runner against them)
118
+
bun run test:cpp # C++ engine tests for both packages (host clang++)
119
+
bun run build # lib/ for both packages: ES modules, CommonJS and declarations
119
120
bun example ios # or: bun example android
120
121
cd docs && npm install && npm start # docs site
121
122
```
@@ -124,6 +125,10 @@ Releasing: `bun --cwd packages/<package> release <patch|minor|major>` runs the t
124
125
125
126
The example's Android Gradle files point at the workspace root `node_modules`, and Metro watches the whole repo.
126
127
128
+
## Known issue: view props on Android
129
+
130
+
Nitro Modules 0.37 never fills a Hybrid View's raw props on Android from React Native 0.86 on, so `backgroundColor`, `border*`, `opacity`, `transform`, `testID` and the accessibility props you pass to `<RollingNumber>` or `<NitroInput>` are silently ignored there. iOS is unaffected. The fix is filed upstream as [margelo/nitro#1655](https://github.com/margelo/nitro/pull/1655) (issue [#1656](https://github.com/margelo/nitro/issues/1656)); until a Nitro release carries it, apply the patch this repo uses: copy [`patches/react-native-nitro-modules@0.37.1.patch`](patches/react-native-nitro-modules@0.37.1.patch) into your app and register it under `patchedDependencies` in `package.json` (Bun) or with [patch-package](https://github.com/ds300/patch-package) (npm / Yarn).
131
+
127
132
## Credits
128
133
129
134
The input's morph is based on [Torph](https://torph.lochie.me) by [Lochie Axon](https://github.com/lochie). Thanks for building it.
Copy file name to clipboardExpand all lines: docs/input/multiline.mdx
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -19,4 +19,6 @@ description: 'multiline: a field that wraps, grows with its content or scrolls p
19
19
20
20
## What a multiline field is not
21
21
22
-
A multiline field is always drawn by the system view and is always `mode="text"`. The glyph engine lays one run out on one baseline, so it cannot morph wrapped text, and an amount or a mask is a single-line idea. `morph`, `mode="number"` and `mode="mask"` are ignored alongside `multiline`, with one warning in development. Everything else applies: a [frame](/input/frames) with a floating label, `maxLength`, autocorrect and the edit callbacks.
22
+
A multiline field is always drawn by the system view and is always `mode="text"`. The glyph engine lays one run out on one baseline, so it cannot morph wrapped text, and an amount, a mask and their affixes are single-line ideas. `morph`, `mode="number"`, `mode="mask"`, `prefix` and `suffix` are ignored alongside `multiline`, with one warning each in development. Everything else applies: a [frame](/input/frames) with a floating label, `maxLength`, autocorrect and the edit callbacks.
23
+
24
+
The return key inserts a line break, as it does on a multiline `TextInput`: `submitBehavior` defaults to `'newline'` there. Pass `submitBehavior="blurAndSubmit"` (or the older `blurOnSubmit`) to have it fire `onSubmitEditing` and dismiss the keyboard instead, or `'submit'` to fire it and keep focus.
Copy file name to clipboardExpand all lines: docs/input/props.mdx
+5-3Lines changed: 5 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -25,17 +25,19 @@ The full table is in the package [README](https://github.com/ronickg/react-nativ
25
25
|`adjustsFontSizeToFit`, `minimumFontScale`, `allowFontScaling`, `maxFontSizeMultiplier`|`false`, `0.5`, `false`, `0`| Shrinking to fit a width, and following the system text size. |
26
26
|`cursorColor`, `selectionColor`, `caretHidden`|| The caret and the selection. |
|`inputMode`, `enterKeyHint`|| React Native's HTML-style aliases for `keyboardType` and `returnKeyType`, mapped with its tables; the explicit prop wins. `inputMode="none"` focuses without a keyboard. |
28
29
|`transform`|| A worklet mask, run synchronously on the UI thread. |
29
-
|`onChangeText`, `onChangeValue`, `onFocus`, `onBlur`, `onSubmitEditing`, `onEndEditing`, `onSelectionChange`, `onKeyPress`||`TextInput`'s edit callbacks, plus `onChangeValue`. Any of them marked `'worklet'` runs on the UI thread instead of the JS one — see [Worklets](/input/worklets). |
30
+
|`onChangeText`, `onChange`, `onChangeValue`, `onFocus`, `onBlur`, `onSubmitEditing`, `onEndEditing`, `onSelectionChange`, `onKeyPress`||`TextInput`'s edit callbacks, plus `onChangeValue`. Each event carries `nativeEvent` as `TextInput`'s does, with the same fields repeated at the top level. Any of them marked `'worklet'` runs on the UI thread instead of the JS one — see [Worklets](/input/worklets). |
30
31
|`onChangeMask`||`'mask'`: the formatted text, the extracted value, the missing tail and whether every mandatory slot is filled. |
31
32
|`value`, `defaultValue`|| Controlled and uncontrolled text. A `value` with a stale `mostRecentEventCount` is ignored, like `TextInput`. |
32
-
|`submitBehavior`|`'blurAndSubmit'`|`'submit'` keeps focus so a form can move to the next field itself. |
33
+
|`submitBehavior`|`'blurAndSubmit'`, `'newline'` when `multiline`|`'submit'` keeps focus so a form can move to the next field itself; `'newline'` inserts a line break (`multiline` only). `blurOnSubmit` is the deprecated alias, resolved as `TextInput` resolves it. |
33
34
|`secureTextEntry`|`false`| Draws bullets; the field keeps the real text for autofill. |
|`selectTextOnFocus`, `clearTextOnFocus`, `contextMenuHidden`, `spellCheck`, `readOnly`|| As on `TextInput`. |
37
38
|`selection`||`{ start, end? }` in code points, controlled. |
39
+
|`id`, `aria-label`, `testID`, `accessibilityLabel`||`id` and `aria-label` are resolved like `TextInput`'s and win over the older spellings; `testID` and the label are forwarded to the system field, the element VoiceOver, TalkBack and e2e tools interact with. |
Imperative handle: `focus()`, `blur()`, `clear()`, `setText()`, `setValue()`, `getText()`, `getValue()`, `isFocused()`, `setSelection()`, and `native`, the Nitro object.
40
42
41
43
Hook: `useNitroInputState(useSharedValue)` — the field's `text`, `value`, `focused` and `selection` as shared values, plus the worklet `handlers` that keep them current. See [the field's state as shared values](/input/worklets#the-fields-state-as-shared-values).
Copy file name to clipboardExpand all lines: docs/rolling-number/props.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,7 +14,7 @@ description: Every prop and method of RollingNumber.
14
14
15
15
| Prop | Type | Default | Description |
16
16
| --- | --- | --- | --- |
17
-
|`value`|`number`| – | The number to display. Every change rolls each digit natively. |
17
+
|`value`|`number`| – | The number to display. Every change rolls each digit natively. At most 18 digits are shown: `|value| × 10^fractionDigits` is clamped at 10^17, and a JS number carries exact integers only up to 2^53. |
18
18
|`fractionDigits`|`number`|`0`| Digits after the decimal separator (0–9). |
19
19
|`minimumIntegerDigits`|`number`|`1`| Zero-pads the integer part (1–15). |
20
20
|`groupingSeparator`|`string`|`''`| Inserted every three integer digits. |
0 commit comments