Skip to content

Implement USER_SELECT flow input in the JavaScript core and React SDK - #106

Open
Dilusha-Madushan wants to merge 1 commit into
thunder-id:mainfrom
Dilusha-Madushan:feature/user-select-input
Open

Dilusha-Madushan wants to merge 1 commit into
thunder-id:mainfrom
Dilusha-Madushan:feature/user-select-input

Conversation

@Dilusha-Madushan

Copy link
Copy Markdown

Purpose

Adds a new built-in flow input, USER_SELECT: a paginated, scrollable single-user picker that submits the selected user's ID. It supports both a consumer-supplied fetchUsers loader and a default authenticated loader wired through InviteUser/BaseInviteUser.

Approach

  • Core (@thunderid/javascript): a UserSelect member on EmbeddedFlowComponentType, an endpoints.users config key resolved through the existing resolveResourceEndpoint precedence, and a getUsers directory helper. Paging and label/value mapping live behind a generic PagedSelect contract (PagedSelectOption/Page/Request, PagedSelectOptionMapping) rather than a user-specific one, so a future EMAIL_SELECT only needs a new loader — not a parallel set of utilities. Mapping rules: plain strings/numbers use themselves as both label and value; a configured labelAttributes/valueAttribute (or getLabel/getValue) wins when set; an unconfigured object falls back by shape (a record with id labels from display → username → email → id; an {label, value} object is used as-is; anything else uses its first text field for both).
  • React: a headless usePagedSelect hook (lazy first page, incremental paging, de-duplication, cancellation via AbortController, a generation guard against stale responses) backs a PagedSelect primitive (floating-ui popover, FormControl/InputLabel composition, role="listbox"/"option", an aria-live status region) and a thin UserSelect specialization supplying the user loader's defaults and wording. Wired into AuthOptionFactory.tsx as a new case EmbeddedFlowComponentType.UserSelect, and a default authenticated fetchUsers is threaded through BaseInviteUser/InviteUser for the case where a consumer doesn't supply their own loader.
  • i18n: picker wording (aria-label, empty/loading/retry/load-more text) and the generic load-failure fallback now resolve through the SDK's translation bundle instead of hardcoded English literals, with new keys added to all 9 locale bundles (the 8 non-English translations are a first pass and should get a native-speaker review before release).
  • Error display follows the existing mapCredentialUpdateError convention: a new mapPagedSelectError returns {message?, messageKey} — a ThunderIDError's message is trusted and shown as-is, anything else (a bare Error, a custom loader's arbitrary throw) falls back to the generic, translatable message, so a picker never surfaces an unreviewed exception string.

Related Issues

Related PRs

  • N/A

Checklist

  • Followed the contribution guidelines.
  • Manual test round performed and verified.
  • Documentation provided. (Add links if there are any)
  • Tests provided. (Add links if there are any)
    • Unit Tests
    • Integration Tests
  • Breaking changes. (Fill if applicable)
    • Breaking changes section filled.
    • breaking change label added.
  • Cross-SDK parity. Exactly one of parity/prs-raised or parity/prs-not-needed added.
    • If parity/prs-raised, the port links are posted as a reply on the parity check's comment.

Security checks

  • Followed secure coding standards.
  • Confirmed that this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets.

Signed-off-by: Dilusha-Madushan <dilushamadushan9912@gmail.com>
@coderabbitai

coderabbitai Bot commented Sep 28, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Repository: thunder-id/javascript-sdks/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 821b143d-cf04-4593-94f3-98f24404da56


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

🔀 Cross-SDK feature parity

Does this change need to ship in the other ThunderID SDKs too? This check stays red until one of these labels answers that:

Label What it asserts
parity/prs-raised The ports exist in every other SDK this change reaches, or are recorded as not applying there.
parity/prs-not-needed Nothing to port: a fix, refactor, docs, CI, dependency bump, release, or a change specific to this platform.

Ports (DO NOT EDIT)

  • thunder-id/ios-sdks, iOS
  • thunder-id/android-sdks, Android
  • thunder-id/flutter-sdks, Flutter

No sibling SDKs accounted for on this thread yet.

Important

Reply to this comment with this block, filled in. The boxes above tick
themselves when you post it.

- thunder-id/ios-sdks: <paste the port link here>
- thunder-id/android-sdks: <paste the port link here>
- thunder-id/flutter-sdks: <paste the port link here>

A link can be a pull request or a tracked issue, written in full or as thunder-id/ios-sdks#123.
Where the change does not reach an SDK, replace the placeholder with N/A and a short
reason, as in - thunder-id/ios-sdks: N/A, the capability has no equivalent there.

The contract is in the SDK development specification.

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.

1 participant