udecode

Activity

Stars and mentions · Last 30 days, Oct 5 – Nov 3

GitHub stars72
Mentions2
02468Oct 5Oct 19Nov 3
UTC days · repositories udecode owns2 repositories

Top repositories

udecode’s repositories ranked by new stars, as on trending.

Loading

Contributes to

Repositories outside udecode’s account where udecode opened or reviewed pull requests in the past 365 days.

Who noticed udecode

Everyone who starred or forked udecode’s repositories since the archive began in 2011.

Notable accounts

Ordered by the stars their own repositories have received.

Biggest fans

Accounts that starred the most of these repositories.

Breakout weeks

Each repository’s best week of new stars, with the release published around it.

Mentions

2posts
Nov 40 posts
  1. 15 merged IME fixes: the recurring ways Japanese typing breaks web apps --- title: "15 merged IME fixes: the recurring ways Japanese typing breaks web apps" published: true tags: javascript, webdev, i18n, a11y --- Between late June and early July 2026 I had 15 pull requests merged into open-source projects, all fixing the same family of bug: a keyboard handler that does not know an input method editor (IME) is in the middle of composing text. This post groups them into the bug classes that keep recurring, with a minimal repro and the fix pattern for each. Every fix links to the merged PR so you can read the real diff. Background in one paragraph Japanese, Chinese and Korean are typed through an IME. In Japanese you type the reading (toukyou), the IME shows candidates (東京), and you press Enter to confirm the candidate. That Enter is a real keydown event. While composition is active, KeyboardEvent.isComposing is true (MDN), and keydowns handled by the IME carry the special keyCode 229 (MDN keydown, which shows the guard if (event.isComposing || event.keyCode === 229) return;). Code that reads only event.key === "Enter" cannot tell "confirm this kanji" from "send this message". Class 1: Enter sends the message mid-composition What the user sees: they type a reading, press Enter to pick the kanji, and the chat sends half a sentence in romaji or unconverted kana. Minimal repro: textarea.addEventListener("keydown", (e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); send(); } }); Fix pattern: textarea.addEventListener("keydown", (e) => { if (e.isComposing || e.keyCode === 229) return; if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); send(); } }); Merged evidence: - CopilotKit/CopilotKit #5764: Angular chat input submitted during composition. - misskey-dev/misskey #17646: chat sent while the IME was composing; the guard also checks e.key === "Process". - twentyhq/twenty #22270: chat-thread input and attachment rename input. - enricoros/big-AGI #1145: custom instruction field in the Diagrams view. Class 2: Enter commits a partial value (tags, list items, renames, validated fields) What the user sees: a tag chip, list item, card title or file name is saved as the unconverted reading, and the actual kanji they picked ends up as a second stray entry, or is lost. In a validated numeric or formatted field, the half-typed value is committed and validated. Minimal repro: input.addEventListener("keydown", (e) => { if (e.key === "Enter" && input.value.trim()) addTag(input.value); }); Fix pattern: the same guard, placed before any commit or validation runs. input.addEventListener("keydown", (e) => { if (e.isComposing || e.keyCode === 229) return; if (e.key === "Enter" && input.value.trim()) addTag(input.value); }); In React, several of these PRs (onyx, payload, rsuite, LibreChat) read e.nativeEvent.isComposing, because the handler receives React's synthetic event rather than the DOM KeyboardEvent. Merged evidence: - tusen-ai/naive-ui #8115: n-dynamic-tags committed a tag on the confirm Enter; the PR includes a test that triggers compositionstart and then Enter. - onyx-dot-app/onyx #12511: ListFieldInput added an item on the confirm Enter. - LibreChat-AI/LibreChat #13996: prompt name, labels and dynamic tag inputs. - TriliumNext/Trilium #10315: board card and column titles. - siyuan-note/siyuan #17988: agent session rename input. - chakra-ui/zag #3198: the color picker channel input committed a partial value on the confirm Enter. Class 3: Enter selects or searches on unconfirmed text What the user sees: in an autocomplete, picker or search box, the confirm Enter picks whatever option is highlighted, or fires the search with the reading instead of the converted word. Minimal repro: combo.addEventListener("keydown", (e) => { if (e.key === "Enter") selectHighlighted(); }); Fix pattern: guard first, then select. In component libraries the guard belongs in the shared keydown handler so every consumer gets it. Merged evidence: - payloadcms/payload #17138: SearchInput searched on the confirm Enter. - rsuite/rsuite #4585: InputPicker selected an item; the PR adds a test that onChange is not called for Enter with isComposing: true. - vuetifyjs/vuetify #22974: VAutocomplete keydown listener ran during composition. Related, no PR of mine behind it: search-as-you-type that fires on every input event also queries the unconfirmed reading while the user is still choosing candidates. InputEvent.isComposing is true for those events (MDN), so a common pattern is to skip them and run the query from compositionend instead. Whether that is what your users want is a product choice; I have not tested this pattern across browsers for this post. Class 4: keyCode 229 where isComposing is false What the user sees: the fix from Class 1 works in Chrome, but the bug is still there for some Safari users. Why: the plate PR below documents the Safari plus Japanese IME case where the confirm Enter arrives with keyCode === 229 and isComposing === false. A guard that reads only isComposing lets it through. I did not reproduce this in Safari myself; the claim rests on that PR and on MDN's recommended guard checking both. Fix pattern: always check both, e.isComposing || e.keyCode === 229. keyCode is deprecated, but this is the one place it still carries information. Merged evidence: - udecode/plate #5048: the floating link editor submitted on the Safari confirm Enter. - misskey-dev/misskey #17646 (also in Class 1) checks isComposing, key === "Process" and keyCode === 229. Class 5: composition flags that depend on event order What the user sees: the same as Class 1 or 2, but only in one browser. Minimal repro: let composing = false; input.addEventListener("compositionstart", () => (composing = true)); input.addEventListener("compositionend", () => (composing = false)); input.addEventListener("keydown", (e) => { if (!composing && e.key === "Enter") submit(); }); Why it breaks: the flag is only correct if the confirm keydown arrives before compositionend. The UI Events spec (section 3.6.5, "Key Events During Composition") says keydown events sent during the composition session must have isComposing set to true. The plate PR in Class 4 shows Safari delivering the confirm Enter with isComposing false, which is consistent with that keydown landing outside the session, after compositionend has already cleared your flag. I have not measured the event order in Safari or any other browser for this post; treat browser-specific ordering as untested. Fix pattern: read the state off the event itself (e.isComposing || e.keyCode === 229) instead of, or in addition to, a flag you maintain. Where a library keeps an instance flag, as naive-ui #8115 does with its input's composition state, add a test that fires Enter during an active composition. A bonus class: Escape during composition Pressing Escape to cancel the IME candidate list also fires keydown with isComposing: true. If a modal or drawer closes on Escape, it closes while the user only meant to cancel the candidates. - Tencent/tdesign-vue-next #6756: the drawer closed on the composition-cancel Escape; the fix is if (e.key === "Escape" && e.isComposing) return; plus a test. Test your own app in 5 minutes You do not need to read Japanese. Add the Japanese IME in your OS settings (Windows: Settings, Time & language, Language, add Japanese; macOS: System Settings, Keyboard, Input Sources, add Japanese - Romaji). 1. Switch to Japanese input and focus your chat box. Type toukyou, press Space to see candidates, press Enter once to confirm. Expected: 東京 stays in the box and nothing is sent. Press Enter again; now it sends. 2. Repeat in every field where Enter does something: tag inputs, list editors, rename fields, inline title editing, search boxes, autocompletes, comboboxes. 3. With candidates open, press Escape. Expected: the candidate list closes and your modal or drawer stays open. 4. In a search-as-you-type box, type a reading slowly and watch the network tab. Decide whether queries for the unconverted reading are acceptable. 5. Grep your code for key === "Enter", key === 'Enter', keyCode === 13 and "Escape", and check each handler has isComposing || keyCode === 229 before it acts. If your handlers set flags in compositionstart and compositionend, check them against step 1 in every browser you support. If you can only test on Windows, steps 1 to 4 do not cover the Safari cases in Classes 4 and 5; step 5 does, by reading the code. --- This article and the fixes it links were drafted with Claude Code and reviewed by the author. If you would rather have someone else run this check on your app, I offer it at ime-check.vercel.app.

    3 reactions · 2 comments
  2. @nebulo_codes @tharshan_09 @joesadoski @poteto @steipete Run sync-pstack, it will set it up to your taste. My twists on pstack: - no worktrees: the main agent writes all code - panels: Opus/Astra/Sol instead of Opus/Fable/Sonnet - your custom playbooks that extend pstack ones github.com/udecode/dotai/tree/main/skills/sync-ps…

    1 like · 26 views

Achievements

Awards earned by the repositories udecode owns. Select an award to embed its badge.

Gold
01st place finishes
Silver
02nd place finishes
Bronze
13rd place finishes
Awarded repositories
1Owned by udecode now

Repositories

Ordered by gold, then silver, then bronze.

  1. plateBest: 3rd by stars, 765 stars001

Every award

Top-three finishes of these repositories in completed trending days and weeks, newest first.

  1. plate

A repository earns an award for finishing first, second or third in a completed trending day or week, ranked by new stars, new forks or pull request authors. Awards follow a repository through renames and transfers and count toward its current owner. Weeks run Monday to Sunday, UTC.