Repository navigation
Support placeholder, maxLength, and filter for pxtJsonOptions input - #11723
Dmitriy Antipov (THEb0nny) wants to merge 10 commits into
Conversation
- Separate PxtJsonOption into discriminated union (checkbox | input) - Add placeholder, maxLength, and filter to PxtJsonInputOption - Support maxLength and fix global regex matching for filter in Input component - Pass placeholder, maxLength, and filter to Input in pxt.json editor
|
Richard Knoll (@riknoll) please take a look |
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved input-handling regressions remove digit limits, discard valid pasted characters, and can disrupt Chinese IME composition, while new placeholders lack translation registration.
4 open issues
What changed in this PR
This follow-up to #10725 extends target-defined pxtJsonOptions text inputs with placeholder hints, length limits, and character filtering in the project settings editor.
Changes:
- Split option typings into checkbox and input variants, with optional input-specific properties.
- Add
maxLengthsupport and global regex matching to the sharedInputcomponent. - Forward placeholder localization lookups, length limits, and filters from project settings.
| File | Description |
|---|---|
webapp/src/pxtjson.tsx |
Passes the new input options to the settings controls. |
react-common/components/controls/Input.tsx |
Adds native length limits and global filter matching. |
localtypings/pxtarget.d.ts |
Defines separate option variants and the new input properties. |
Review effort: Max
- Filter complete pasted text before applying maxLength in Input - Preserve IME composition state during typing in Input - Register pxtJsonOptions input placeholder in targetStrings in cli - Limit CriteriaInstanceDisplay numeric input with maxLength and digit filter
There was a problem hiding this comment.
🟡 Changes recommended
Replacing the public PxtJsonOption interface with a union breaks target extensions and declaration merging, while unresolved filtered-input defects can delete existing characters or save invalid text.
8 open issues
Enforce a zero maxLength when a filter is set · New Avoid splitting surrogate pairs at the maxLength boundary · New Limit inserted text without truncating the existing suffix · New Preserve the caret when sanitizing filtered input · New Skip onChange when composition ends without a committed change · New Preserve input method composition until it completes Register input placeholders for translation Limit numeric input to two digits
1 resolved since last review
Review effort: Max
- Preserve caret position after sanitizing filtered input in changeHandler and compositionEndHandler - Handle onPaste to filter clipboard text and limit insertion without truncating existing suffix - Track lastCommittedValue to skip onChange when composition is cancelled
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved paste, IME, and validation defects can corrupt text, break undo, bypass length limits, and leave consumer state out of sync with the displayed value.
12 open issues
Enforce maxLength after IME composition · New Sync the committed-value ref after Enter validation · New Preserve intermediate callbacks for unconstrained IME input · New Allow native paste for non-text clipboard contents · New Strip line breaks from pasted text before filtering · New Filter the prospective full value on paste · New Truncate pasted text at code-point boundaries · New Preserve undo history for valid native pastes · New Avoid splitting surrogate pairs at the maxLength boundary Preserve input method composition until it completes Register input placeholders for translation Limit numeric input to two digits
4 resolved since last review
Review effort: Max
There was a problem hiding this comment.
🟡 Changes recommended
Filtering clipboard text in isolation rejects valid insertions, while unguarded selection handling can throw or mishandle pastes on number and email inputs.
5 open issues
8 resolved since last review
Preserve undo history for valid native pastes Truncate pasted text at code-point boundaries Strip line breaks from pasted text before filtering Allow native paste for non-text clipboard contents Preserve intermediate callbacks for unconstrained IME input Sync the committed-value ref after Enter validation Enforce maxLength after IME composition Avoid splitting surrogate pairs at the maxLength boundary
Review effort: Max
There was a problem hiding this comment.
🔵 Needs a closer look
Human review is needed to assess input-filtering edge cases affecting caret placement, paste consistency, composition preservation, and regex safety that were omitted from the published review.
1 open issue
4 resolved since last review
Review effort: Max
There was a problem hiding this comment.
🟡 Changes recommended
Filtered paste can lose cross-boundary regex matches and clear or duplicate existing text, while regression tests for paste behavior and length clamping are missing.
2 open issues
1 resolved since last review
Review effort: Max
|
Joey Wunderlich (@jwunderl) Everything has been verified: |

Description
This PR follows up on #10725 by adding support for
placeholder,maxLength, andfilterforpxtJsonOptionsof type"input"inpxt.json.This enables targets (such as
pxt-ev3for project folder names) to restrict input values, enforce character limits, and provide meaningful placeholder hints.Changes:
localtypings/pxtarget.d.ts:PxtJsonOptioninto a discriminated union (PxtJsonCheckboxOption | PxtJsonInputOption), ensuring strict typing and autocomplete for option properties based ontype.placeholder?: string,maxLength?: number, andfilter?: stringtoPxtJsonInputOption.webapp/src/pxtjson.tsx:placeholder(localized withpxt.Util.rlf),maxLength, andfilterto the<Input />component.cli/cli.ts:{id:setting}${option.placeholder}intotargetStringsduringsaveThemeJsonfor Crowdin localization extraction.react-common/components/controls/Input.tsx:maxLength?: numberprop support.filterto match globally (/g).truncateToCodePointBoundary) to prevent splitting UTF-16 surrogate pairs (emoji) atmaxLength.getSelection/setCaret) guarding againstDOMExceptionon inputs that do not support selection offsets (e.g.type="number"/type="email").\r/\n) from pasted text in single-line inputs.prefix + paste + suffix) and derived retained insertion and caret position.document.execCommand("insertText")for sanitized pastes.compositionstart/compositionend) to avoid interrupting multi-step character entry (e.g. CJK), while keeping intermediate callbacks active for unconstrained inputs (SearchInput, etc.).lastCommittedValueRefacross change, blur, and Enter validation to prevent suppressing legitimate edits and spurious consumer state resets.filteris undefined.teachertool/src/components/CriteriaInstanceDisplay.tsx:filter="[0-9]"alongsidemaxLength={numeric && !paramOptions ? 2 : undefined}to align with global filter regex matching.Testing:
npx gulp cli(passed)npx gulp reactCommon(passed)npx gulp webapp(passed)npx gulp lint(passed, 0 errors across codebase)pxt-ev3):uploadProjectFolderwithplaceholder: "BrkProg_SAVE",maxLength: 20, andfilter: "[a-zA-Z0-9_-]":maxLength, preserves existing suffixes, and supports Ctrl+Z undo.Example target configuration (
pxtarget.json)