feat(demo): add image upload to try your own images - #17
Merged
Conversation
Adds an "Upload image…" action to the demo sidebar backed by a hidden file input. The file is read client-side via FileReader.readAsDataURL and flows through the existing image prop / serialized reset chain — no server involved. Hardening from adversarial review: - MIME + 20 MB size gate (accept="image/*" is only a picker hint) - read token + abort so a slow read can't overwrite a newer pick - reader.error logged; input value cleared before the callback so re-selecting the same file always fires onChange Co-Authored-By: Claude <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an "Upload image…" action to the demo sidebar so users can try the editor with their own images (requested follow-up to the sample-image rotation).
demo/src/Sidebar.tsx— new Actions button backed by a hidden<input type="file" accept="image/*">; input value is cleared before the callback so re-selecting the same file always firesonChange.demo/src/App.tsx—uploadImage()reads the file client-side viaFileReader.readAsDataURLand passes the data URL through the existingimageprop / serialized reset chain. No server, no persistence — the image never leaves the visitor's browser, so this works unchanged on static hosting (Vercel).Hardening from adversarial review (cross-model confirmed findings, fixed in-branch):
acceptis only a picker hint — non-image/*files and files > 20 MB are rejected with a status message before any read.reader.abort()ensures a slow read of a large file can never overwrite a newer pick (upload or "Change image") after the fact.reader.erroris logged on failure; previously it was silently discarded.Test Coverage
Tests: 2 → 2 (+0 new) — all 8 new code paths live in
demo/, which is intentionally outside the library's test boundary (vitest scopes tosrc/**). Verified manually in the running demo instead: valid upload, non-image rejection, oversize rejection, picker cancel, same-file re-select, and "Change image" recovery all confirmed in-browser.Pre-Landing Review
No issues found. (Small diff — specialists skipped per policy.)
Adversarial Review
Claude adversarial subagent + Codex (
model_reasoning_effort=high), both ran:reader.errorswallowed; input value cleared after callback (Claude)onLoadErrorpath.Eval Results
No prompt-related files changed — evals skipped.
Scope Drift
Scope Check: CLEAN — intent was "add image upload to the demo"; the diff touches exactly the two demo files.
Plan Completion
No plan file detected.
Verification Results
Manual browser verification against the live dev server (post-fix): 6 PASS, 0 FAIL — valid image load,
.txtrejection ("is not an image"), 21 MB file rejection ("too large (max 20 MB)"), same-file re-select, picker cancel no-op, sample-image cycling after upload.Documentation
Documentation is current — README doesn't enumerate demo sidebar actions (pre-existing convention). Flagged as optional debt for
/document-generate.Test plan
tsc --noEmitclean (root + demo)🤖 Generated with Claude Code