Skip to content

Commit e937685

Browse files
jkomorosclaudehappy-otterbfollington
authored
Add PDF support via ct-file-input base component (commontoolsinc#2151)
* feat(ui): Add ct-file-input base component Create generic file upload component that can handle any file type. Features: - Accepts any file type via 'accept' attribute - Smart preview rendering based on MIME type (images vs documents) - Protected methods for subclass extension (processFile, renderPreview, etc.) - No compression logic in base class - Cell-based reactive data binding This component serves as the base for ct-image-input and enables PDF/document upload use cases. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <[email protected]> Co-Authored-By: Happy <[email protected]> * refactor(ui): Refactor ct-image-input to extend ct-file-input Convert ct-image-input from standalone component to subclass of ct-file-input. Changes: - Extends CTFileInput instead of BaseElement - ImageData now extends FileData - Compression logic moved to override methods - Image dimension extraction in processFile override - Capture attribute added via renderFileInput override - Backward compatibility maintained via property aliases (images/maxImages) - Event details include both 'images' and 'files' properties This reduces code duplication and establishes clear inheritance hierarchy while maintaining full backward compatibility with existing code. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <[email protected]> Co-Authored-By: Happy <[email protected]> * test(ui): Add manual test file for ct-file-input and ct-image-input Create HTML test page to verify: - ct-file-input with PDF support - ct-file-input with mixed image/PDF support - ct-image-input backward compatibility (images property) - ct-image-input camera capture support Test file includes event listeners to verify both 'images' and 'files' properties are present for backward compatibility. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <[email protected]> Co-Authored-By: Happy <[email protected]> * feat(types): Add JSX types for ct-file-input component Add TypeScript JSX definitions for ct-file-input: - CTFileInputElement interface - CTFileInputAttributes interface with all properties - IntrinsicElements entry for JSX support This enables type-safe usage of ct-file-input in patterns. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <[email protected]> Co-Authored-By: Happy <[email protected]> * fix: Address cubic code review issues 1. **maxSizeBytes now used in ct-file-input**: Added console.warn when files exceed size threshold 2. **max-file guard fixed**: Only enforces limit in multiple mode, allowing single-file replacement 3. **Removed test-file-input.html**: Browser cannot load TypeScript directly; test-file-upload.tsx pattern serves this purpose 4. **Fixed ct-image-input handler conflict**: Made parent _handleFileChange protected, subclass calls via super 5. **Fixed event recursion**: Override emit() method to add backward-compat properties instead of listening/re-emitting These changes ensure proper file validation, fix single-file selection replacement, and eliminate infinite recursion in event handling. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <[email protected]> Co-Authored-By: Happy <[email protected]> * fix: Address additional cubic code review issues - Move maxSizeBytes check to after compression so it validates the final file size - Fix max file guard to only apply in multiple mode, allowing single-file replacement - Note: test-file-input.html import issue is moot as file was removed in earlier commit Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <[email protected]> Co-Authored-By: Happy <[email protected]> * Remove test files, screenshots, and bug reports from PR These files were accidentally included and are not part of the ct-file-input/ct-image-input PDF support feature: - 76 playwright screenshot files - 8 bug report and documentation files - 11 test pattern files - package.json/package-lock.json (playwright test dependency) This reduces the PR from 6,656 lines to just the actual feature code. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <[email protected]> Co-Authored-By: Happy <[email protected]> * Format and lint --------- Co-authored-by: Claude <[email protected]> Co-authored-by: Happy <[email protected]> Co-authored-by: Ben Follington <[email protected]>
1 parent 1487939 commit e937685

File tree

4 files changed

+692
-378
lines changed

4 files changed

+692
-378
lines changed

packages/html/src/jsx.d.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2864,6 +2864,7 @@ interface CTListElement extends CTHTMLElement {}
28642864
interface CTListItemElement extends CTHTMLElement {}
28652865
interface CTLoaderElement extends CTHTMLElement {}
28662866
interface CTInputElement extends CTHTMLElement {}
2867+
interface CTFileInputElement extends CTHTMLElement {}
28672868
interface CTImageInputElement extends CTHTMLElement {}
28682869
interface CTInputLegacyElement extends CTHTMLElement {}
28692870
interface CTCheckboxElement extends CTHTMLElement {}
@@ -3247,6 +3248,32 @@ interface CTInputLegacyAttributes<T> extends CTHTMLAttributes<T> {
32473248
"customStyle"?: string;
32483249
}
32493250

3251+
interface CTFileInputAttributes<T> extends CTHTMLAttributes<T> {
3252+
"multiple"?: boolean;
3253+
"maxFiles"?: number;
3254+
"accept"?: string;
3255+
"buttonText"?: string;
3256+
"variant"?:
3257+
| "default"
3258+
| "primary"
3259+
| "secondary"
3260+
| "outline"
3261+
| "ghost"
3262+
| "link"
3263+
| "destructive";
3264+
"size"?: "default" | "sm" | "lg" | "icon";
3265+
"showPreview"?: boolean;
3266+
"previewSize"?: "sm" | "md" | "lg";
3267+
"removable"?: boolean;
3268+
"disabled"?: boolean;
3269+
"maxSizeBytes"?: number;
3270+
"files"?: any[]; // FileData[]
3271+
"$files"?: any; // CellLike<FileData[]>
3272+
"onct-change"?: EventHandler<any>;
3273+
"onct-remove"?: EventHandler<any>;
3274+
"onct-error"?: EventHandler<any>;
3275+
}
3276+
32503277
interface CTImageInputAttributes<T> extends CTHTMLAttributes<T> {
32513278
"multiple"?: boolean;
32523279
"maxImages"?: number;
@@ -3811,6 +3838,10 @@ declare global {
38113838
CTInputAttributes<CTInputElement>,
38123839
CTInputElement
38133840
>;
3841+
"ct-file-input": CTDOM.DetailedHTMLProps<
3842+
CTFileInputAttributes<CTFileInputElement>,
3843+
CTFileInputElement
3844+
>;
38143845
"ct-image-input": CTDOM.DetailedHTMLProps<
38153846
CTImageInputAttributes<CTImageInputElement>,
38163847
CTImageInputElement

0 commit comments

Comments
 (0)