Skip to content

input_otp: replace otp.js with pure Rust and fix demo structure#35

Closed
krishpranav wants to merge 2 commits intorust-ui:mainfrom
krishpranav:feat/issue-26-otp-rust-migration
Closed

input_otp: replace otp.js with pure Rust and fix demo structure#35
krishpranav wants to merge 2 commits intorust-ui:mainfrom
krishpranav:feat/issue-26-otp-rust-migration

Conversation

@krishpranav
Copy link
Copy Markdown
Contributor

Description:

The OTP component still depended on a JavaScript controller and the docs page was rendering the OTP demos through one shared wrapper that made the layout feel wrong.
This patch moves the OTP controller into Rust with web_sys, removes the runtime JS file, and restructures the Input OTP docs page so each demo block behaves independently with its own local Preview and Code controls.

What changed:

  • Replaced the OTP JavaScript controller with a Rust web_sys implementation in use_input_otp
  • Wired InputOTP to initialize the Rust controller directly and removed the script tag
  • Deleted public/app_components/otp.js
  • Updated the registry snapshots and tree entries for the Rust-based OTP implementation
  • Rebuilt demo_input_otp.rs so the OTP page renders independent demo blocks for basic input, 4-digit variant, digit filter, focus/blur, and post-hydration init
  • Added per-block Preview and Code toggles with block-local state for the OTP docs page
  • Bypassed the shared top-level demo wrapper controls for the Input OTP page so the local block controls are the only ones shown

Validation:

cargo build
cargo clippy -- -D warnings

Screenshot

Input OTP demo screenshot 1 Input OTP demo screenshot 2

Input OTP demo screenshot 3

Closes #26

Replace the OTP JavaScript controller with a Rust/web_sys implementation and wire InputOTP to initialize it directly. Update the docs demo so each OTP scenario renders as an independent block with its own local Preview and Code controls, and bypass the shared demo wrapper toolbar for the OTP page so the layout matches the intended structure.
Copy link
Copy Markdown
Contributor

@max-wells max-wells left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@krishpranav Thanks for the contribution! The core direction is right — removing the JS file and porting to web_sys is exactly what the issue asked for. Two things to address before this can be merged.

}) as Box<dyn FnMut(web_sys::Event)>);

let _ = target.add_event_listener_with_callback("beforeinput", listener.as_ref().unchecked_ref());
listener.forget();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Memory leaklistener.forget() leaks the closure because there is no cleanup path. The same closure pattern is used in use_input_otp.rs via _listeners: Vec<Listener> which cleans up on drop — this beforeinput listener should follow the same approach. Using .forget() is usually a last resort in WASM; here it can be avoided by storing the closure in the _listeners vec so it gets dropped with the controller.

pub fn StaticDemoWrapper(demo_type: MarkdownType, children: Children) -> impl IntoView {
let current_tab = RwSignal::new(Tab::default());
let use_embedded_blocks = matches!(demo_type, MarkdownType::StaticDemoInputOtp);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This use_embedded_blocks flag was not part of issue #26 — the issue only asked to replace otp.js with Rust. Modifying StaticDemoWrapper to hardcode a special case for OTP is a smell: it couples a generic wrapper to a specific component, and it will need to be repeated for every future component that wants the same behavior. Please revert the changes to demo_input_otp.rs and static_demo_wrapper.rs and open a separate issue/PR if the demo layout needs improvement.

@krishpranav
Copy link
Copy Markdown
Contributor Author

@max-wells the changes are done. kindly review it

@max-wells
Copy link
Copy Markdown
Contributor

max-wells commented May 2, 2026

Thanks for the contribution! The core Rust port was solid — I applied the relevant changes (use_input_otp hook, input_otp.rs wiring, otp.js removal, registry updates) cleanly on main, rebased on top of the latest markdown crate work. The demo restructuring was left out to keep demo_input_otp.rs consistent with the rest of the project.

@max-wells max-wells closed this May 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replace otp.js with a Rust implementation using web_sys

2 participants