You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* feat(CodeEditor): add download functionality for editor content
- Introduced a new method to download the current editor content as a file, with the extension determined by the selected programming language.
- Updated the CodeEditorHandle and CodeEditorContext interfaces to include the new downloadContent method.
- Added a mapping of language names to their corresponding file extensions to facilitate the download process.
* feat(Panel): implement download functionality in the editor panel
- Added a new handleDownloadClick method to the Panel component to trigger the downloadContent function from the CodeEditorContext.
- Updated the onClick handler for the Download menu item to use the new method, enhancing the user experience by allowing content downloads directly from the panel.
* feat(tests): add unit tests for download functionality in CodeEditor and Panel
- Implemented comprehensive tests for the download feature in the CodeEditor, verifying correct filename generation based on language and handling of empty content.
- Enhanced Panel tests to ensure the downloadContent function is called when the download menu item is clicked, including handling cases where the function is not available.
- Improved test coverage for the download functionality, ensuring robustness and reliability in the editor's user experience.
* feat(CodeEditor): add comprehensive download functionality for editor content
- Introduced a `downloadContent` method to the CodeEditor ref for programmatic file downloads, supporting various file extensions based on the editor's language.
- Integrated a download button in the Panel's secondary menu for direct content downloads, with proper filename handling.
- Enhanced context support for child components via `CodeEditorContext`, allowing custom UI implementations for downloads.
- Implemented content validation to prevent downloads of empty or whitespace-only content, providing user-friendly warnings.
- Updated TypeScript definitions and added extensive tests to ensure robust functionality and user experience.
* docs(README): update Panel component description and add download functionality details
- Enhanced the description of the Panel component to include the new download button and its integration with the CodeEditor's functionality.
- Updated the properties table to reflect the addition of the download feature, including the `onDownloadClick` callback and its behavior.
- Added a new section detailing the `downloadContent` method, including examples and supported file extensions for improved documentation clarity.
* refactor(tests): streamline Panel tests for download functionality
- Updated Panel tests to utilize the new renderPanel utility, improving clarity and reducing redundancy.
- Simplified test cases for the downloadContent function, ensuring proper handling when the function is undefined.
- Enhanced test maintainability by integrating default context functions for download actions.
* refactor(CodeEditor): move language extension mapping to constants file
- Extracted the LANGUAGE_EXTENSION_MAP from CodeEditor.tsx to a new constants.ts file for better organization and maintainability.
- Simplified the extension determination logic in CodeEditor.tsx by directly referencing the imported LANGUAGE_EXTENSION_MAP.
* docs(CodeEditor): update download function
* feat(Panel): add downloadFileName property for customizable download filenames
- Introduced the `downloadFileName` property to the Panel component, allowing users to specify a custom filename for downloaded editor content.
- Updated the download handling logic to utilize the provided filename, enhancing the flexibility of the download functionality.
- Added tests to ensure correct behavior when the `downloadFileName` is specified or omitted.
* docs(README): correct default filename behavior in downloadContent example
- Updated the example in the README to clarify that the default behavior of the downloadContent method results in the file being downloaded as 'code' when no filename parameter is provided, rather than 'code.py'. This enhances the accuracy of the documentation for users.
**Feature**: Add download functionality to CodeEditor component
6
+
7
+
-**Imperative API**: Added `downloadContent(filename?)` method to CodeEditor ref handle for programmatic file downloads
8
+
-**Smart file extensions**: Automatic file extension mapping based on editor language (`.js`, `.ts`, `.py`, `.css`, etc.) with fallback to `.txt`
9
+
-**Panel integration**: Download button in Panel secondary menu now performs actual file downloads with proper filename handling
10
+
-**Context support**: Download function available to child components via `CodeEditorContext` for custom UI implementations
11
+
-**Content validation**: Prevents downloads of empty or whitespace-only content with user-friendly warnings
12
+
-**Enhanced TypeScript**: Complete `downloadContent` method documentation in `CodeEditorHandle` interface
13
+
-**Comprehensive testing**: Behavior-focused tests that verify actual download triggers rather than implementation details
14
+
-**Language support**: Built-in extension mapping for 16+ languages including JavaScript, TypeScript, Python, Java, Go, Rust, and more
15
+
16
+
**Technical implementation**: Uses browser-native Blob API and temporary anchor elements for downloads. Maintains full backward compatibility while adding new download capabilities. Language extension mapping ensures downloaded files have appropriate extensions for syntax highlighting in external editors.
The Panel component provides a toolbar interface for the CodeEditor with formatting, copying, and custom action buttons. It displays at the top of the CodeEditor and can include a title, action buttons, and custom content.
80
+
The Panel component provides a toolbar interface for the CodeEditor with formatting, copying, download, and custom action buttons. It displays at the top of the CodeEditor and can include a title, action buttons, and custom content. When used within a CodeEditor, the Panel automatically integrates with the editor's functionality - the download button performs actual file downloads with appropriate extensions, undo/redo buttons operate on the editor history, and the format button processes the editor content.
81
81
82
82
#### Example
83
83
@@ -94,6 +94,7 @@ import CloudIcon from '@leafygreen-ui/icon';
94
94
showFormatButton
95
95
showCopyButton
96
96
showSecondaryMenuButton
97
+
downloadFileName="my-script.js"
97
98
customSecondaryButtons={[
98
99
{
99
100
label: 'Deploy to Cloud',
@@ -112,22 +113,23 @@ import CloudIcon from '@leafygreen-ui/icon';
|`baseFontSize`_(optional)_| Font size of text in the panel. Controls the typography scale used for the panel title and other text elements. |`14 \| 16`|`14`|
118
-
|`customSecondaryButtons`_(optional)_| Array of custom secondary buttons to display in the secondary menu. Each button can include a label, icon, click handler, href, and aria-label for accessibility. |`Array<SecondaryButtonConfig>`|`undefined`|
119
-
|`darkMode`_(optional)_| Determines if the component appears in dark mode. When not provided, the component will inherit the dark mode state from the LeafyGreen Provider. |`boolean`|`undefined`|
120
-
|`innerContent`_(optional)_| React node to render between the title and the buttons. Can be used to add custom controls to the panel. |`React.ReactNode`|`undefined`|
121
-
|`onCopyClick`_(optional)_| Callback fired when the copy button is clicked. Called after the copy operation is attempted. |`() => void`|`undefined`|
122
-
|`onDownloadClick`_(optional)_| Callback fired when the download button in the secondary menu is clicked. Called after the download operation is attempted. |`() => void`|`undefined`|
123
-
|`onFormatClick`_(optional)_| Callback fired when the format button is clicked. Called after the formatting operation is attempted. |`() => void`|`undefined`|
124
-
|`onRedoClick`_(optional)_| Callback fired when the redo button in the secondary menu is clicked. Called after the redo operation is attempted. |`() => void`|`undefined`|
125
-
|`onUndoClick`_(optional)_| Callback fired when the undo button in the secondary menu is clicked. Called after the undo operation is attempted. |`() => void`|`undefined`|
126
-
|`onViewShortcutsClick`_(optional)_| Callback fired when the view shortcuts button in the secondary menu is clicked. Called after the view shortcuts operation is attempted. |`() => void`|`undefined`|
127
-
|`showCopyButton`_(optional)_| Determines whether to show the copy button in the panel. When enabled, users can copy the editor content to their clipboard. |`boolean`|`undefined`|
128
-
|`showFormatButton`_(optional)_| Determines whether to show the format button in the panel. When enabled and formatting is available for the current language, users can format/prettify their code. |`boolean`|`undefined`|
129
-
|`showSecondaryMenuButton`_(optional)_| Determines whether to show the secondary menu button (ellipsis icon) in the panel. When enabled, displays a menu with additional actions like undo, redo, download, and view shortcuts. |`boolean`|`undefined`|
130
-
|`title`_(optional)_| Title text to display in the panel header. Typically used to show the current language or content description. |`string`|`undefined`|
|`baseFontSize`_(optional)_| Font size of text in the panel. Controls the typography scale used for the panel title and other text elements. |`14 \| 16`|`14`|
119
+
|`customSecondaryButtons`_(optional)_| Array of custom secondary buttons to display in the secondary menu. Each button can include a label, icon, click handler, href, and aria-label for accessibility. |`Array<SecondaryButtonConfig>`|`undefined`|
120
+
|`darkMode`_(optional)_| Determines if the component appears in dark mode. When not provided, the component will inherit the dark mode state from the LeafyGreen Provider. |`boolean`|`undefined`|
121
+
|`downloadFileName`_(optional)_| Optional filename to use when downloading the editor content. If provided, the file will be downloaded with this exact filename. If not provided, uses the default filename 'code' with appropriate extension based on language. |`string`|`undefined`|
122
+
|`innerContent`_(optional)_| React node to render between the title and the buttons. Can be used to add custom controls to the panel. |`React.ReactNode`|`undefined`|
123
+
|`onCopyClick`_(optional)_| Callback fired when the copy button is clicked. Called after the copy operation is attempted. |`() => void`|`undefined`|
124
+
|`onDownloadClick`_(optional)_| Callback fired when the download button in the secondary menu is clicked. Called after the actual file download is triggered. When used within CodeEditor, downloads the editor content automatically. |`() => void`|`undefined`|
125
+
|`onFormatClick`_(optional)_| Callback fired when the format button is clicked. Called after the formatting operation is attempted. |`() => void`|`undefined`|
126
+
|`onRedoClick`_(optional)_| Callback fired when the redo button in the secondary menu is clicked. Called after the redo operation is attempted. |`() => void`|`undefined`|
127
+
|`onUndoClick`_(optional)_| Callback fired when the undo button in the secondary menu is clicked. Called after the undo operation is attempted. |`() => void`|`undefined`|
128
+
|`onViewShortcutsClick`_(optional)_| Callback fired when the view shortcuts button in the secondary menu is clicked. Called after the view shortcuts operation is attempted. |`() => void`|`undefined`|
129
+
|`showCopyButton`_(optional)_| Determines whether to show the copy button in the panel. When enabled, users can copy the editor content to their clipboard. |`boolean`|`undefined`|
130
+
|`showFormatButton`_(optional)_| Determines whether to show the format button in the panel. When enabled and formatting is available for the current language, users can format/prettify their code. |`boolean`|`undefined`|
131
+
|`showSecondaryMenuButton`_(optional)_| Determines whether to show the secondary menu button (ellipsis icon) in the panel. When enabled, displays a menu with additional actions like undo, redo, download, and view shortcuts. |`boolean`|`undefined`|
132
+
|`title`_(optional)_| Title text to display in the panel header. Typically used to show the current language or content description. |`string`|`undefined`|
131
133
132
134
#### `SecondaryButtonConfig`
133
135
@@ -238,6 +240,12 @@ function MyComponent() {
238
240
}
239
241
};
240
242
243
+
const handleDownload = () => {
244
+
if (editorRef.current) {
245
+
editorRef.current.downloadContent('my-script'); // Downloads as 'my-script.js'
@@ -263,8 +272,30 @@ The `CodeEditorHandle` provides the following methods:
263
272
-**`isFormattingAvailable`** - Boolean indicating if formatting is available for the current language
264
273
-**`undo()`** - Undoes the last editor action, returns boolean indicating success
265
274
-**`redo()`** - Redoes the last undone action, returns boolean indicating success
275
+
-**`downloadContent(filename?)`** - Downloads the editor content as a file. If filename is provided, used exactly as-is; if not provided, defaults to 'code' with appropriate extension
266
276
-**`getEditorViewInstance()`** - Returns the underlying CodeMirror EditorView instance
267
277
278
+
#### Download Functionality
279
+
280
+
The `downloadContent` method uses a simple approach to filename handling:
281
+
282
+
-**When a filename is provided**: Uses the filename exactly as provided, with no modifications
283
+
-**When no filename is provided**: Uses the default filename 'code' and adds an appropriate extension based on the editor's language
284
+
285
+
```tsx
286
+
// Downloads as 'script' (uses filename exactly as provided)
287
+
editorRef.current.downloadContent('script');
288
+
289
+
// Downloads as 'my-file.py' (uses filename exactly as provided)
290
+
editorRef.current.downloadContent('my-file.py');
291
+
292
+
// Downloads as 'code' (uses filename exactly as provided, even though it's "code")
293
+
editorRef.current.downloadContent('code');
294
+
295
+
// Downloads as 'code' (default behavior - no filename parameter provided)
296
+
editorRef.current.downloadContent(); // No filename provided
0 commit comments