feat(sufi-blazor): introduce sb mark editor unified editing surface
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
@namespace SufiChain.SufiBlazor.Components.Forms
|
||||
@using SufiChain.SufiBlazor.Contracts.Editors
|
||||
|
||||
<SbMarkdownEditor Value="@Value"
|
||||
ValueChanged="@ValueChanged"
|
||||
ValueHtml="@ValueHtml"
|
||||
ValueHtmlChanged="@ValueHtmlChanged"
|
||||
ReadOnly="@ReadOnly"
|
||||
Disabled="@Disabled"
|
||||
Placeholder="@Placeholder"
|
||||
Class="@Class"
|
||||
Style="@Style"
|
||||
RightToLeft="@RightToLeft"
|
||||
EnablePreview="@EnablePreview"
|
||||
EnableMermaid="@EnableMermaid"
|
||||
EnableHighlight="@EnableHighlight"
|
||||
HighlightTheme="@HighlightTheme"
|
||||
EditorMode="@ResolveEditorMode()"
|
||||
SourceLanguage="@ResolveSourceLanguage()"
|
||||
UseToolbarContributors="@UseToolbarContributors"
|
||||
IncludeDefaultToolbarItems="@IncludeDefaultToolbarItems"
|
||||
HideToolbar="@HideToolbar"
|
||||
ToolbarItems="@ToolbarItems"
|
||||
OnShortcut="@OnShortcut"
|
||||
MinHeight="@MinHeight"
|
||||
MaxHeight="@MaxHeight"
|
||||
FallbackRows="@FallbackRows"
|
||||
IsDiffReview="@IsDiffReview"
|
||||
OriginalValue="@OriginalValue"
|
||||
SuggestedValue="@SuggestedValue"
|
||||
SuggestedValueChanged="@SuggestedValueChanged"
|
||||
OnApplyChanges="@OnApplyChanges"
|
||||
OnDiscardChanges="@OnDiscardChanges"
|
||||
AdditionalAttributes="@AdditionalAttributes" />
|
||||
@@ -0,0 +1,65 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using SufiChain.SufiBlazor.Contracts.Editors;
|
||||
|
||||
namespace SufiChain.SufiBlazor.Components.Forms;
|
||||
|
||||
public partial class SbMarkEditor
|
||||
{
|
||||
[Parameter] public string Value { get; set; } = string.Empty;
|
||||
[Parameter] public EventCallback<string> ValueChanged { get; set; }
|
||||
[Parameter] public string? ValueHtml { get; set; }
|
||||
[Parameter] public EventCallback<string?> ValueHtmlChanged { get; set; }
|
||||
[Parameter] public bool ReadOnly { get; set; }
|
||||
[Parameter] public bool Disabled { get; set; }
|
||||
[Parameter] public string? Placeholder { get; set; }
|
||||
[Parameter] public string? Class { get; set; }
|
||||
[Parameter] public string? Style { get; set; }
|
||||
[Parameter] public bool RightToLeft { get; set; }
|
||||
[Parameter] public bool EnablePreview { get; set; } = true;
|
||||
[Parameter] public bool EnableMermaid { get; set; } = true;
|
||||
[Parameter] public bool EnableHighlight { get; set; } = true;
|
||||
[Parameter] public string HighlightTheme { get; set; } = "github";
|
||||
[Parameter] public SbMarkEditorMode Mode { get; set; } = SbMarkEditorMode.Markdown;
|
||||
[Parameter] public string? SourceLanguage { get; set; }
|
||||
[Parameter] public bool UseToolbarContributors { get; set; }
|
||||
[Parameter] public bool IncludeDefaultToolbarItems { get; set; } = true;
|
||||
[Parameter] public bool HideToolbar { get; set; }
|
||||
[Parameter] public IReadOnlyList<SbMarkdownToolbarItem>? ToolbarItems { get; set; }
|
||||
[Parameter] public EventCallback<string> OnShortcut { get; set; }
|
||||
[Parameter] public string? MinHeight { get; set; } = "200px";
|
||||
[Parameter] public string? MaxHeight { get; set; }
|
||||
[Parameter] public int FallbackRows { get; set; } = 12;
|
||||
[Parameter] public bool IsDiffReview { get; set; }
|
||||
[Parameter] public string OriginalValue { get; set; } = string.Empty;
|
||||
[Parameter] public string SuggestedValue { get; set; } = string.Empty;
|
||||
[Parameter] public EventCallback<string> SuggestedValueChanged { get; set; }
|
||||
[Parameter] public EventCallback OnApplyChanges { get; set; }
|
||||
[Parameter] public EventCallback OnDiscardChanges { get; set; }
|
||||
[Parameter(CaptureUnmatchedValues = true)]
|
||||
public Dictionary<string, object>? AdditionalAttributes { get; set; }
|
||||
|
||||
private SbMarkdownEditorMode ResolveEditorMode()
|
||||
{
|
||||
return Mode switch
|
||||
{
|
||||
SbMarkEditorMode.Source => SbMarkdownEditorMode.Source,
|
||||
SbMarkEditorMode.Markup => SbMarkdownEditorMode.Source,
|
||||
_ => SbMarkdownEditorMode.Markdown
|
||||
};
|
||||
}
|
||||
|
||||
private string? ResolveSourceLanguage()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(SourceLanguage))
|
||||
{
|
||||
return SourceLanguage;
|
||||
}
|
||||
|
||||
return Mode switch
|
||||
{
|
||||
SbMarkEditorMode.Markup => "html",
|
||||
SbMarkEditorMode.Source => "html",
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace SufiChain.SufiBlazor.Contracts.Editors;
|
||||
|
||||
public enum SbMarkEditorMode
|
||||
{
|
||||
Markdown,
|
||||
Markup,
|
||||
Source
|
||||
}
|
||||
@@ -323,6 +323,7 @@ export async function initEditor(textarea, dotNetRef, options) {
|
||||
easyOptions.preview = false;
|
||||
easyOptions.sideBySideFullscreen = false;
|
||||
} else {
|
||||
easyOptions.sideBySideFullscreen = false;
|
||||
easyOptions.previewRender = buildPreviewRender(options);
|
||||
easyOptions.renderingConfig.markedOptions = {
|
||||
highlight: buildHighlightFn(options.enableHighlight, options.enableMermaid)
|
||||
@@ -435,6 +436,20 @@ export function insertTextAtCursor(editorId, text) {
|
||||
cm.focus();
|
||||
}
|
||||
|
||||
function toggleContainerFullscreen(stored) {
|
||||
const wrapper = stored.easyMDE.codemirror.getWrapperElement();
|
||||
const container = wrapper?.closest('.sb-markdown-editor');
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
container.classList.toggle('sb-markdown-editor--fullscreen');
|
||||
document.documentElement.classList.toggle(
|
||||
'sb-markdown-editor-fullscreen-active',
|
||||
container.classList.contains('sb-markdown-editor--fullscreen'));
|
||||
stored.easyMDE.codemirror.refresh();
|
||||
}
|
||||
|
||||
export function execAction(editorId, action, value) {
|
||||
const stored = editors.get(editorId);
|
||||
if (!stored) {
|
||||
@@ -457,7 +472,7 @@ export function execAction(editorId, action, value) {
|
||||
case 'image': easyMDE.drawImage(); break;
|
||||
case 'preview': easyMDE.togglePreview(); break;
|
||||
case 'side-by-side': easyMDE.toggleSideBySide(); break;
|
||||
case 'fullscreen': easyMDE.toggleFullScreen(); break;
|
||||
case 'fullscreen': toggleContainerFullscreen(stored); break;
|
||||
case 'undo': easyMDE.codemirror.undo(); break;
|
||||
case 'redo': easyMDE.codemirror.redo(); break;
|
||||
default:
|
||||
|
||||
@@ -8445,6 +8445,55 @@ body.sb-resizing {
|
||||
color: var(--sb-color-text);
|
||||
}
|
||||
|
||||
.sb-markdown-editor .EasyMDEContainer.sided--no-fullscreen {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sb-markdown-editor .EasyMDEContainer.sided--no-fullscreen .CodeMirror-sided,
|
||||
.sb-markdown-editor .EasyMDEContainer.sided--no-fullscreen .editor-preview-side {
|
||||
flex: 1 1 50%;
|
||||
width: 50% !important;
|
||||
min-width: 20rem;
|
||||
position: static !important;
|
||||
inset: auto !important;
|
||||
height: auto;
|
||||
max-height: none;
|
||||
}
|
||||
|
||||
.sb-markdown-editor .EasyMDEContainer.sided--no-fullscreen .editor-preview-active-side {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sb-markdown-editor-fullscreen-active,
|
||||
.sb-markdown-editor-fullscreen-active body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sb-markdown-editor.sb-markdown-editor--fullscreen {
|
||||
position: fixed;
|
||||
inset: var(--sb-space-4);
|
||||
z-index: 2000;
|
||||
min-height: auto;
|
||||
background: var(--sb-color-surface);
|
||||
box-shadow: var(--sb-shadow-xl, 0 24px 64px rgba(15, 23, 42, 0.22));
|
||||
}
|
||||
|
||||
.sb-markdown-editor.sb-markdown-editor--fullscreen .EasyMDEContainer {
|
||||
flex: 1 1 auto;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.sb-markdown-editor.sb-markdown-editor--fullscreen .EasyMDEContainer .CodeMirror {
|
||||
height: calc(100vh - 9rem) !important;
|
||||
}
|
||||
|
||||
.sb-markdown-editor.sb-markdown-editor--fullscreen .EasyMDEContainer.sided--no-fullscreen .CodeMirror-sided,
|
||||
.sb-markdown-editor.sb-markdown-editor--fullscreen .EasyMDEContainer.sided--no-fullscreen .editor-preview-side {
|
||||
height: calc(100vh - 9rem) !important;
|
||||
}
|
||||
|
||||
.sb-markdown-viewer pre,
|
||||
.sb-markdown-viewer code {
|
||||
font-family: var(--sb-font-family-mono, monospace);
|
||||
|
||||
Reference in New Issue
Block a user