feat(wysiwyg): Add language selection for code blocks, block settings menu, fix cursor navigation, and update demo to use dees-panel
- Added modal to select programming language when creating code blocks - Added settings button (3 dots) on each block for configuration - Fixed cursor not jumping to new block after pressing Enter - Special handling for code blocks: Enter creates new line, Shift+Enter creates new block - Display language indicator on code blocks - Updated demo to use dees-panel instead of demo-section divs - Added language selection in block settings modal for existing code blocks
This commit is contained in:
@ -301,35 +301,11 @@ export const demoFunc = () => html`
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.demo-section {
|
||||
background: #f8f9fa;
|
||||
border-radius: 12px;
|
||||
padding: 32px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
dees-panel {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.demo-section {
|
||||
background: #1a1a1a;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.demo-section h3 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 20px;
|
||||
color: #0066cc;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.demo-section h3 {
|
||||
color: #4d94ff;
|
||||
}
|
||||
}
|
||||
|
||||
.demo-section p {
|
||||
dees-panel p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 24px;
|
||||
color: #666;
|
||||
@ -338,7 +314,7 @@ export const demoFunc = () => html`
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.demo-section p {
|
||||
dees-panel p {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
@ -448,8 +424,7 @@ export const demoFunc = () => html`
|
||||
</style>
|
||||
|
||||
<div class="demo-container">
|
||||
<div class="demo-section">
|
||||
<h3>🚀 Modern WYSIWYG Editor</h3>
|
||||
<dees-panel .heading=${'🚀 Modern WYSIWYG Editor'}>
|
||||
<p>A powerful block-based editor with slash commands, keyboard shortcuts, and multiple output formats. Perfect for content creation, blog posts, documentation, and more.</p>
|
||||
|
||||
<div class="feature-list">
|
||||
@ -521,10 +496,9 @@ export const demoFunc = () => html`
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</dees-panel>
|
||||
|
||||
<div class="demo-section">
|
||||
<h3>📝 Blog Post Example</h3>
|
||||
<dees-panel .heading=${'📝 Blog Post Example'}>
|
||||
<p>Perfect for creating rich content with multiple block types. The editor preserves formatting and provides a clean editing experience.</p>
|
||||
|
||||
<dees-input-wysiwyg
|
||||
@ -533,10 +507,9 @@ export const demoFunc = () => html`
|
||||
.value=${'<h1>Welcome to Our Blog</h1><p>This is an example blog post that demonstrates the capabilities of our WYSIWYG editor.</p><h2>Features Overview</h2><p>Our editor supports multiple block types including headings, paragraphs, quotes, and more.</p><blockquote>The best way to predict the future is to invent it.</blockquote><p>You can also create lists and code blocks for technical content.</p>'}
|
||||
.outputFormat=${'html'}
|
||||
></dees-input-wysiwyg>
|
||||
</div>
|
||||
</dees-panel>
|
||||
|
||||
<div class="demo-section">
|
||||
<h3>🔀 Drag & Drop Reordering</h3>
|
||||
<dees-panel .heading=${'🔀 Drag & Drop Reordering'}>
|
||||
<p>Easily rearrange your content blocks by dragging them. Hover over any block to reveal the drag handle on the left side.</p>
|
||||
|
||||
<dees-input-wysiwyg
|
||||
@ -555,10 +528,9 @@ export const demoFunc = () => html`
|
||||
<li>The editor maintains focus on the moved block after dropping</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</dees-panel>
|
||||
|
||||
<div class="demo-section">
|
||||
<h3>📚 Tutorial & Documentation</h3>
|
||||
<dees-panel .heading=${'📚 Tutorial & Documentation'}>
|
||||
<p>Create comprehensive tutorials and documentation with code examples, lists, and structured content.</p>
|
||||
|
||||
<dees-input-wysiwyg
|
||||
@ -567,10 +539,9 @@ export const demoFunc = () => html`
|
||||
.outputFormat=${'markdown'}
|
||||
.value=${'# Git Tutorial for Beginners\n\nGit is a distributed version control system that helps you track changes in your code over time. This tutorial will guide you through the basics.\n\n## Prerequisites\n\nBefore starting, ensure you have:\n\n- Git installed on your system\n- A text editor or IDE\n- Basic command line knowledge\n\n## Getting Started\n\n### 1. Configure Git\n\nFirst, set up your identity:\n\n```bash\ngit config --global user.name "Your Name"\ngit config --global user.email "your.email@example.com"\n```\n\n### 2. Initialize a Repository\n\nCreate a new Git repository:\n\n```bash\nmkdir my-project\ncd my-project\ngit init\n```\n\n### 3. Basic Git Workflow\n\n#### Adding Files\n\nCreate a file and add it to staging:\n\n```bash\necho "# My Project" > README.md\ngit add README.md\n```\n\n#### Committing Changes\n\n```bash\ngit commit -m "Initial commit"\n```\n\n> **Best Practice:** Write clear, descriptive commit messages that explain what changes were made and why.\n\n### 4. Working with Branches\n\nBranches allow you to work on features independently:\n\n```bash\n# Create and switch to a new branch\ngit checkout -b feature-branch\n\n# Make changes and commit\ngit add .\ngit commit -m "Add new feature"\n\n# Switch back to main\ngit checkout main\n\n# Merge the feature\ngit merge feature-branch\n```\n\n---\n\n## Common Commands Reference\n\n| Command | Description |\n|---------|-------------|\n| `git status` | Check repository status |\n| `git log` | View commit history |\n| `git diff` | Show changes |\n| `git pull` | Fetch and merge changes |\n| `git push` | Upload changes to remote |\n\n## Next Steps\n\n1. Learn about remote repositories\n2. Explore advanced Git features\n3. Practice with real projects\n4. Contribute to open source\n\n**Happy coding!** 🚀'}
|
||||
></dees-input-wysiwyg>
|
||||
</div>
|
||||
</dees-panel>
|
||||
|
||||
<div class="demo-section">
|
||||
<h3>🔄 Output Formats</h3>
|
||||
<dees-panel .heading=${'🔄 Output Formats'}>
|
||||
<p>Choose between HTML and Markdown output formats depending on your needs. Perfect for static site generators, documentation systems, or any content management workflow.</p>
|
||||
|
||||
<div class="output-section">
|
||||
@ -579,7 +550,7 @@ export const demoFunc = () => html`
|
||||
.label=${'Meeting Notes'}
|
||||
.description=${'Structured meeting documentation'}
|
||||
.outputFormat=${'html'}
|
||||
.value=${'<h2>Q4 Planning Meeting</h2><p><strong>Date:</strong> December 15, 2024<br><strong>Attendees:</strong> Product Team, Engineering, Design</p><h3>Agenda Items</h3><ol><li>Review Q3 achievements</li><li>Set Q4 objectives</li><li>Resource allocation</li><li>Timeline discussion</li></ol><h3>Key Decisions</h3><ul><li>Launch new dashboard feature by end of January</li><li>Increase engineering team by 2 developers</li><li>Implement weekly design reviews</li></ul><blockquote>"Focus on user experience improvements based on Q3 feedback" - Product Manager</blockquote><h3>Action Items</h3><ul><li>Sarah: Create detailed project timeline</li><li>Mike: Draft technical requirements</li><li>Lisa: Schedule user research sessions</li></ul><hr><p>Next meeting: January 5, 2025</p>'}
|
||||
.value=${'<h2>Q4 Planning Meeting</h2><p><strong>Date:</strong> December 15, 2024<br><strong>Attendees:</strong> Product Team, Engineering, Design</p><h3>Agenda Items'}><ol><li>Review Q3 achievements</li><li>Set Q4 objectives</li><li>Resource allocation</li><li>Timeline discussion</li></ol><h3>Key Decisions'}><ul><li>Launch new dashboard feature by end of January</li><li>Increase engineering team by 2 developers</li><li>Implement weekly design reviews</li></ul><blockquote>"Focus on user experience improvements based on Q3 feedback" - Product Manager</blockquote><h3>Action Items'}><ul><li>Sarah: Create detailed project timeline</li><li>Mike: Draft technical requirements</li><li>Lisa: Schedule user research sessions</li></ul><hr><p>Next meeting: January 5, 2025</p>'}
|
||||
></dees-input-wysiwyg>
|
||||
</div>
|
||||
|
||||
@ -592,22 +563,20 @@ export const demoFunc = () => html`
|
||||
></dees-input-wysiwyg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</dees-panel>
|
||||
|
||||
<div class="demo-section">
|
||||
<h3>🎨 Advanced Editing</h3>
|
||||
<dees-panel .heading=${'🎨 Advanced Editing'}>
|
||||
<p>Create complex documents with mixed content types. The editor handles all formatting seamlessly.</p>
|
||||
|
||||
<dees-input-wysiwyg
|
||||
.label=${'Technical Documentation'}
|
||||
.description=${'Create technical docs with code examples and structured content'}
|
||||
.value=${'<h1>API Documentation</h1><p>Welcome to our API documentation. Below you\'ll find examples of how to use our endpoints.</p><h2>Authentication</h2><p>All API requests require authentication using an API key:</p><pre><code>Authorization: Bearer YOUR_API_KEY</code></pre><h2>Endpoints</h2><h3>GET /users</h3><p>Retrieve a list of users from the system.</p><pre><code>curl -X GET https://api.example.com/users \\\n -H "Authorization: Bearer YOUR_API_KEY"</code></pre><blockquote>Note: Rate limiting applies to all endpoints. You can make up to 100 requests per minute.</blockquote><h3>POST /users</h3><p>Create a new user in the system.</p><pre><code>{\n "name": "John Doe",\n "email": "john@example.com",\n "role": "user"\n}</code></pre><hr><p>For more information, please refer to our complete documentation.</p>'}
|
||||
.value=${'<h1>API Documentation</h1><p>Welcome to our API documentation. Below you\'ll find examples of how to use our endpoints.</p><h2>Authentication</h2><p>All API requests require authentication using an API key:</p><pre><code>Authorization: Bearer YOUR_API_KEY</code></pre><h2>Endpoints</h2><h3>GET /users'}><p>Retrieve a list of users from the system.</p><pre><code>curl -X GET https://api.example.com/users \\\n -H "Authorization: Bearer YOUR_API_KEY"</code></pre><blockquote>Note: Rate limiting applies to all endpoints. You can make up to 100 requests per minute.</blockquote><h3>POST /users'}><p>Create a new user in the system.</p><pre><code>{\n "name": "John Doe",\n "email": "john@example.com",\n "role": "user"\n}</code></pre><hr><p>For more information, please refer to our complete documentation.</p>'}
|
||||
.outputFormat=${'html'}
|
||||
></dees-input-wysiwyg>
|
||||
</div>
|
||||
</dees-panel>
|
||||
|
||||
<div class="demo-section">
|
||||
<h3>⚙️ Form Integration</h3>
|
||||
<dees-panel .heading=${'⚙️ Form Integration'}>
|
||||
<p>Seamlessly integrates with dees-form for complete form solutions. All standard form features like validation, required fields, and data binding work out of the box.</p>
|
||||
|
||||
<dees-form>
|
||||
@ -631,10 +600,9 @@ export const demoFunc = () => html`
|
||||
.tags=${['web-development', 'javascript', 'tutorial']}
|
||||
></dees-input-tags>
|
||||
</dees-form>
|
||||
</div>
|
||||
</dees-panel>
|
||||
|
||||
<div class="demo-section">
|
||||
<h3>🧩 Programmatic Block Creation</h3>
|
||||
<dees-panel .heading=${'🧩 Programmatic Block Creation'}>
|
||||
<p>Create content programmatically using the block API for dynamic document generation.</p>
|
||||
|
||||
<dees-input-wysiwyg
|
||||
@ -659,10 +627,9 @@ export const demoFunc = () => html`
|
||||
style="padding: 8px 16px; border: 1px solid #ddd; border-radius: 4px; background: #f8f8f8; cursor: pointer;"
|
||||
>Clear Editor</button>
|
||||
</div>
|
||||
</div>
|
||||
</dees-panel>
|
||||
|
||||
<div class="demo-section">
|
||||
<h3>📤 Export/Import Features</h3>
|
||||
<dees-panel .heading=${'📤 Export/Import Features'}>
|
||||
<p>The WYSIWYG editor provides multiple export formats and lossless save/restore capabilities for maximum flexibility.</p>
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 16px; margin-bottom: 24px;">
|
||||
@ -746,7 +713,7 @@ export const demoFunc = () => html`
|
||||
}}
|
||||
>Restore State</button>
|
||||
</div>
|
||||
</div>
|
||||
</dees-panel>
|
||||
</div>
|
||||
</dees-demowrapper>
|
||||
`;
|
@ -1,5 +1,6 @@
|
||||
import { DeesInputBase } from '../dees-input-base.js';
|
||||
import { demoFunc } from '../dees-input-wysiwyg.demo.js';
|
||||
import { DeesModal } from '../dees-modal.js';
|
||||
|
||||
import {
|
||||
customElement,
|
||||
@ -204,6 +205,22 @@ export class DeesInputWysiwyg extends DeesInputBase<string> {
|
||||
onCompositionEnd: () => this.isComposing = false,
|
||||
onMouseUp: (e: MouseEvent) => this.handleTextSelection(e),
|
||||
})}
|
||||
${block.type !== 'divider' ? html`
|
||||
<div
|
||||
class="block-settings"
|
||||
@click="${(e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.showBlockSettingsModal(block);
|
||||
}}"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
||||
<circle cx="12" cy="5" r="2"></circle>
|
||||
<circle cx="12" cy="12" r="2"></circle>
|
||||
<circle cx="12" cy="19" r="2"></circle>
|
||||
</svg>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
@ -315,6 +332,23 @@ export class DeesInputWysiwyg extends DeesInputBase<string> {
|
||||
this.updateValue();
|
||||
this.requestUpdate();
|
||||
return;
|
||||
} else if (detectedType.type === 'code') {
|
||||
// For code blocks, ask for language
|
||||
this.showLanguageSelectionModal().then(language => {
|
||||
if (language) {
|
||||
block.type = 'code';
|
||||
block.content = '';
|
||||
block.metadata = { language };
|
||||
|
||||
// Clear the DOM element immediately
|
||||
target.textContent = '';
|
||||
|
||||
// Force update
|
||||
this.updateValue();
|
||||
this.requestUpdate();
|
||||
}
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
// For all other block types
|
||||
block.type = detectedType.type;
|
||||
@ -638,11 +672,22 @@ export class DeesInputWysiwyg extends DeesInputBase<string> {
|
||||
}
|
||||
}
|
||||
|
||||
private insertBlock(type: IBlock['type']) {
|
||||
private async insertBlock(type: IBlock['type']) {
|
||||
const currentBlockIndex = this.blocks.findIndex(b => b.id === this.selectedBlockId);
|
||||
const currentBlock = this.blocks[currentBlockIndex];
|
||||
|
||||
if (currentBlock && currentBlock.content.startsWith('/')) {
|
||||
// If it's a code block, ask for language
|
||||
if (type === 'code') {
|
||||
const language = await this.showLanguageSelectionModal();
|
||||
if (!language) {
|
||||
// User cancelled
|
||||
this.closeSlashMenu();
|
||||
return;
|
||||
}
|
||||
currentBlock.metadata = { language };
|
||||
}
|
||||
|
||||
currentBlock.type = type;
|
||||
currentBlock.content = '';
|
||||
|
||||
@ -1027,4 +1072,142 @@ export class DeesInputWysiwyg extends DeesInputBase<string> {
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
|
||||
private async showLanguageSelectionModal(): Promise<string | null> {
|
||||
return new Promise((resolve) => {
|
||||
let selectedLanguage: string | null = null;
|
||||
|
||||
DeesModal.createAndShow({
|
||||
heading: 'Select Programming Language',
|
||||
content: html`
|
||||
<style>
|
||||
.language-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 8px;
|
||||
padding: 16px;
|
||||
}
|
||||
.language-button {
|
||||
padding: 12px;
|
||||
background: var(--dees-color-box);
|
||||
border: 1px solid var(--dees-color-line-bright);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.language-button:hover {
|
||||
background: var(--dees-color-box-highlight);
|
||||
border-color: var(--dees-color-primary);
|
||||
}
|
||||
</style>
|
||||
<div class="language-grid">
|
||||
${['JavaScript', 'TypeScript', 'Python', 'Java', 'C++', 'C#', 'Go', 'Rust', 'HTML', 'CSS', 'SQL', 'Shell', 'JSON', 'YAML', 'Markdown', 'Plain Text'].map(lang => html`
|
||||
<div class="language-button" @click="${(e: MouseEvent) => {
|
||||
selectedLanguage = lang.toLowerCase();
|
||||
// Find and click the hidden OK button to close the modal
|
||||
const modal = (e.target as HTMLElement).closest('dees-modal');
|
||||
if (modal) {
|
||||
const okButton = modal.shadowRoot?.querySelector('.bottomButton.ok') as HTMLElement;
|
||||
if (okButton) okButton.click();
|
||||
}
|
||||
}}">${lang}</div>
|
||||
`)}
|
||||
</div>
|
||||
`,
|
||||
menuOptions: [
|
||||
{
|
||||
name: 'Cancel',
|
||||
action: async (modal) => {
|
||||
modal.destroy();
|
||||
resolve(null);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'OK',
|
||||
action: async (modal) => {
|
||||
modal.destroy();
|
||||
resolve(selectedLanguage);
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private async showBlockSettingsModal(block: IBlock): Promise<void> {
|
||||
let content: TemplateResult;
|
||||
|
||||
if (block.type === 'code') {
|
||||
const currentLanguage = block.metadata?.language || 'plain text';
|
||||
content = html`
|
||||
<style>
|
||||
.settings-section {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.settings-label {
|
||||
font-weight: 500;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.language-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 8px;
|
||||
}
|
||||
.language-button {
|
||||
padding: 8px;
|
||||
background: var(--dees-color-box);
|
||||
border: 1px solid var(--dees-color-line-bright);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.language-button:hover {
|
||||
background: var(--dees-color-box-highlight);
|
||||
border-color: var(--dees-color-primary);
|
||||
}
|
||||
.language-button.selected {
|
||||
background: var(--dees-color-primary);
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
<div class="settings-section">
|
||||
<div class="settings-label">Programming Language</div>
|
||||
<div class="language-grid">
|
||||
${['JavaScript', 'TypeScript', 'Python', 'Java', 'C++', 'C#', 'Go', 'Rust', 'HTML', 'CSS', 'SQL', 'Shell', 'JSON', 'YAML', 'Markdown', 'Plain Text'].map(lang => html`
|
||||
<div class="language-button ${currentLanguage === lang.toLowerCase() ? 'selected' : ''}"
|
||||
@click="${(e: MouseEvent) => {
|
||||
if (!block.metadata) block.metadata = {};
|
||||
block.metadata.language = lang.toLowerCase();
|
||||
this.updateValue();
|
||||
this.requestUpdate();
|
||||
// Find and click the close button
|
||||
const modal = (e.target as HTMLElement).closest('dees-modal');
|
||||
if (modal) {
|
||||
const closeButton = modal.shadowRoot?.querySelector('.bottomButton') as HTMLElement;
|
||||
if (closeButton) closeButton.click();
|
||||
}
|
||||
}}">${lang}</div>
|
||||
`)}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
content = html`<div style="padding: 16px;">No settings available for this block type.</div>`;
|
||||
}
|
||||
|
||||
DeesModal.createAndShow({
|
||||
heading: 'Block Settings',
|
||||
content,
|
||||
menuOptions: [
|
||||
{
|
||||
name: 'Close',
|
||||
action: async (modal) => {
|
||||
modal.destroy();
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
@ -55,6 +55,30 @@ export class WysiwygBlocks {
|
||||
`;
|
||||
}
|
||||
|
||||
// Special rendering for code blocks with language indicator
|
||||
if (block.type === 'code') {
|
||||
const language = block.metadata?.language || 'plain text';
|
||||
return html`
|
||||
<div class="code-block-container">
|
||||
<div class="code-language">${language}</div>
|
||||
<div
|
||||
class="block ${block.type} ${isSelected ? 'selected' : ''}"
|
||||
contenteditable="true"
|
||||
@input="${handlers.onInput}"
|
||||
@keydown="${handlers.onKeyDown}"
|
||||
@focus="${handlers.onFocus}"
|
||||
@blur="${handlers.onBlur}"
|
||||
@compositionstart="${handlers.onCompositionStart}"
|
||||
@compositionend="${handlers.onCompositionEnd}"
|
||||
@mouseup="${(e: MouseEvent) => {
|
||||
console.log('Block mouseup event fired');
|
||||
if (handlers.onMouseUp) handlers.onMouseUp(e);
|
||||
}}"
|
||||
></div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
return html`
|
||||
<div
|
||||
class="block ${block.type} ${isSelected ? 'selected' : ''}"
|
||||
|
@ -153,16 +153,36 @@ export const wysiwygStyles = css`
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.code-block-container {
|
||||
position: relative;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.code-language {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
background: ${cssManager.bdTheme('#e1e4e8', '#333333')};
|
||||
color: ${cssManager.bdTheme('#586069', '#8b949e')};
|
||||
padding: 4px 12px;
|
||||
font-size: 12px;
|
||||
border-radius: 0 6px 0 6px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
text-transform: lowercase;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.block.code {
|
||||
background: ${cssManager.bdTheme('#f8f8f8', '#0d0d0d')};
|
||||
border: 1px solid ${cssManager.bdTheme('#e0e0e0', '#2a2a2a')};
|
||||
border-radius: 6px;
|
||||
padding: 16px 20px;
|
||||
padding-top: 32px; /* Make room for language indicator */
|
||||
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', monospace;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
white-space: pre-wrap;
|
||||
color: ${cssManager.bdTheme('#d14', '#ff6b6b')};
|
||||
color: ${cssManager.bdTheme('#24292e', '#e1e4e8')};
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
@ -394,6 +414,37 @@ export const wysiwygStyles = css`
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* Block Settings Button */
|
||||
.block-settings {
|
||||
position: absolute;
|
||||
right: -40px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: ${cssManager.bdTheme('#999', '#666')};
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.block-wrapper:hover .block-settings {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.block-settings:hover {
|
||||
color: ${cssManager.bdTheme('#666', '#999')};
|
||||
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.05)', 'rgba(255, 255, 255, 0.05)')};
|
||||
}
|
||||
|
||||
.block-settings:active {
|
||||
background: ${cssManager.bdTheme('rgba(0, 0, 0, 0.1)', 'rgba(255, 255, 255, 0.1)')};
|
||||
}
|
||||
|
||||
/* Text Selection Styles */
|
||||
.block ::selection {
|
||||
background: ${cssManager.bdTheme('rgba(0, 102, 204, 0.3)', 'rgba(77, 148, 255, 0.3)')};
|
||||
|
Reference in New Issue
Block a user