颜色修复
This commit is contained in:
@@ -1209,6 +1209,16 @@ fn target_element(target: web_sys::EventTarget) -> Option<Element> {
|
||||
})
|
||||
}
|
||||
|
||||
fn event_target_matches_selector(
|
||||
target: Option<web_sys::EventTarget>,
|
||||
selector: &str,
|
||||
) -> bool {
|
||||
target
|
||||
.and_then(target_element)
|
||||
.and_then(|element| element.closest(selector).ok().flatten())
|
||||
.is_some()
|
||||
}
|
||||
|
||||
fn current_target_html_element(event: &WheelEvent) -> Option<HtmlElement> {
|
||||
event.current_target()?.dyn_into::<HtmlElement>().ok()
|
||||
}
|
||||
@@ -2250,6 +2260,8 @@ fn App() -> impl IntoView {
|
||||
let (text_selection_active, set_text_selection_active) = signal(false);
|
||||
let (floating_toolbar_anchor, set_floating_toolbar_anchor) =
|
||||
signal(None::<FloatingToolbarAnchor>);
|
||||
let (locked_toolbar_anchor, set_locked_toolbar_anchor) =
|
||||
signal(None::<FloatingToolbarAnchor>);
|
||||
let (slash_open, set_slash_open) = signal(false);
|
||||
let (slash_index, set_slash_index) = signal(0_usize);
|
||||
let (turn_into_open, set_turn_into_open) = signal(false);
|
||||
@@ -2294,6 +2306,18 @@ fn App() -> impl IntoView {
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let turn_into_open = turn_into_open;
|
||||
let color_menu_open = color_menu_open;
|
||||
let more_menu_open = more_menu_open;
|
||||
let set_locked_toolbar_anchor = set_locked_toolbar_anchor;
|
||||
Effect::new(move |_| {
|
||||
if !(turn_into_open.get() || color_menu_open.get() || more_menu_open.get()) {
|
||||
set_locked_toolbar_anchor.set(None);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let editor_focused = editor_focused;
|
||||
let text_selection_active = text_selection_active;
|
||||
@@ -2311,8 +2335,7 @@ fn App() -> impl IntoView {
|
||||
color_menu_open.get_untracked(),
|
||||
more_menu_open.get_untracked(),
|
||||
);
|
||||
if !editor_focused.get()
|
||||
|| (!text_selection_active.get() && !toolbar_locked)
|
||||
if ((!editor_focused.get() || !text_selection_active.get()) && !toolbar_locked)
|
||||
|| slash_open.get()
|
||||
|| block_menu_open.get()
|
||||
{
|
||||
@@ -2390,7 +2413,7 @@ fn App() -> impl IntoView {
|
||||
if let Some(target) = event.target() {
|
||||
if let Some(element) = target_element(target) {
|
||||
if element
|
||||
.closest(HANDLE_SHELL_SELECTOR)
|
||||
.closest(&format!("{HANDLE_SHELL_SELECTOR}, .floating-toolbar"))
|
||||
.ok()
|
||||
.flatten()
|
||||
.is_some()
|
||||
@@ -2808,14 +2831,20 @@ fn App() -> impl IntoView {
|
||||
}
|
||||
>
|
||||
{move || {
|
||||
if let Some(anchor) = floating_toolbar_anchor.get() {
|
||||
let toolbar_locked = toolbar_overlay_locked(
|
||||
turn_into_open.get(),
|
||||
color_menu_open.get(),
|
||||
more_menu_open.get(),
|
||||
);
|
||||
if !editor_focused.get()
|
||||
|| (!text_selection_active.get() && !toolbar_locked)
|
||||
let toolbar_locked = toolbar_overlay_locked(
|
||||
turn_into_open.get(),
|
||||
color_menu_open.get(),
|
||||
more_menu_open.get(),
|
||||
);
|
||||
let toolbar_anchor = if toolbar_locked {
|
||||
locked_toolbar_anchor
|
||||
.get()
|
||||
.or_else(|| floating_toolbar_anchor.get())
|
||||
} else {
|
||||
floating_toolbar_anchor.get()
|
||||
};
|
||||
if let Some(anchor) = toolbar_anchor {
|
||||
if ((!editor_focused.get() || !text_selection_active.get()) && !toolbar_locked)
|
||||
|| slash_open.get()
|
||||
|| block_menu_open.get()
|
||||
|| dragging_block_index.get().is_some()
|
||||
@@ -2829,7 +2858,12 @@ fn App() -> impl IntoView {
|
||||
style:top=format!("{}px", anchor.top)
|
||||
style:left=format!("{}px", anchor.left)
|
||||
on:mousedown=move |event: MouseEvent| {
|
||||
event.prevent_default();
|
||||
if event_target_matches_selector(
|
||||
event.target(),
|
||||
".toolbar-btn, .toolbar-menu-item, .turn-into-item",
|
||||
) {
|
||||
event.prevent_default();
|
||||
}
|
||||
event.stop_propagation();
|
||||
}
|
||||
on:click=move |event: MouseEvent| {
|
||||
@@ -2844,54 +2878,51 @@ fn App() -> impl IntoView {
|
||||
data-active=move || turn_into_open.get().to_string()
|
||||
data-testid="toolbar-turn-into"
|
||||
on:click=move |_| {
|
||||
set_turn_into_open.update(|open| *open = !*open);
|
||||
let next_open = !turn_into_open.get_untracked();
|
||||
if next_open {
|
||||
set_locked_toolbar_anchor
|
||||
.set(floating_toolbar_anchor.get_untracked());
|
||||
}
|
||||
set_turn_into_open.set(next_open);
|
||||
set_block_menu_open.set(false);
|
||||
}
|
||||
>
|
||||
"Text"
|
||||
</button>
|
||||
{move || {
|
||||
if turn_into_open.get() {
|
||||
<div
|
||||
class="turn-into-panel"
|
||||
data-testid="turn-into-panel"
|
||||
style:display=move || if turn_into_open.get() { "grid" } else { "none" }
|
||||
on:mousedown=move |event: MouseEvent| {
|
||||
event.stop_propagation();
|
||||
}
|
||||
on:click=move |event: MouseEvent| {
|
||||
event.stop_propagation();
|
||||
}
|
||||
on:wheel=move |event: WheelEvent| {
|
||||
trap_scroll_inside_menu(&event);
|
||||
}
|
||||
>
|
||||
{SLASH_ACTIONS.iter().map(|action| {
|
||||
let kind = action.kind;
|
||||
let label = action.label;
|
||||
let description = action.description;
|
||||
let testid = format!("turn-into-{}", action.id);
|
||||
view! {
|
||||
<div
|
||||
class="turn-into-panel"
|
||||
data-testid="turn-into-panel"
|
||||
on:mousedown=move |event: MouseEvent| {
|
||||
event.prevent_default();
|
||||
event.stop_propagation();
|
||||
}
|
||||
on:click=move |event: MouseEvent| {
|
||||
event.stop_propagation();
|
||||
}
|
||||
on:wheel=move |event: WheelEvent| {
|
||||
trap_scroll_inside_menu(&event);
|
||||
<button
|
||||
class="turn-into-item"
|
||||
data-testid=testid
|
||||
on:click=move |_| {
|
||||
apply_feedback_result(set_command_feedback, run_slash_action(editor, kind));
|
||||
set_turn_into_open.set(false);
|
||||
}
|
||||
>
|
||||
{SLASH_ACTIONS.iter().map(|action| {
|
||||
let kind = action.kind;
|
||||
let label = action.label;
|
||||
let description = action.description;
|
||||
let testid = format!("turn-into-{}", action.id);
|
||||
view! {
|
||||
<button
|
||||
class="turn-into-item"
|
||||
data-testid=testid
|
||||
on:click=move |_| {
|
||||
apply_feedback_result(set_command_feedback, run_slash_action(editor, kind));
|
||||
set_turn_into_open.set(false);
|
||||
}
|
||||
>
|
||||
{label}
|
||||
<span>{description}</span>
|
||||
</button>
|
||||
}
|
||||
}).collect_view()}
|
||||
</div>
|
||||
}.into_any()
|
||||
} else {
|
||||
().into_any()
|
||||
}
|
||||
}}
|
||||
{label}
|
||||
<span>{description}</span>
|
||||
</button>
|
||||
}
|
||||
}).collect_view()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2959,113 +2990,110 @@ fn App() -> impl IntoView {
|
||||
|| color_menu_open.get()).to_string()
|
||||
data-testid="toolbar-color"
|
||||
on:click=move |_| {
|
||||
set_color_menu_open.update(|open| *open = !*open);
|
||||
let next_open = !color_menu_open.get_untracked();
|
||||
if next_open {
|
||||
set_locked_toolbar_anchor
|
||||
.set(floating_toolbar_anchor.get_untracked());
|
||||
}
|
||||
set_color_menu_open.set(next_open);
|
||||
set_more_menu_open.set(false);
|
||||
set_turn_into_open.set(false);
|
||||
}
|
||||
>
|
||||
"Color"
|
||||
</button>
|
||||
{move || {
|
||||
if color_menu_open.get() {
|
||||
view! {
|
||||
<div
|
||||
class="toolbar-popover-panel"
|
||||
data-testid="toolbar-color-panel"
|
||||
on:mousedown=move |event: MouseEvent| {
|
||||
event.prevent_default();
|
||||
event.stop_propagation();
|
||||
}
|
||||
on:click=move |event: MouseEvent| {
|
||||
event.stop_propagation();
|
||||
}
|
||||
on:wheel=move |event: WheelEvent| {
|
||||
trap_scroll_inside_menu(&event);
|
||||
}
|
||||
>
|
||||
<div class="toolbar-popover-section">
|
||||
<div class="toolbar-popover-title">"文字颜色"</div>
|
||||
<div class="toolbar-color-grid">
|
||||
{TOOLBAR_TEXT_COLORS.iter().map(|option| {
|
||||
let value = option.value;
|
||||
let label = option.label;
|
||||
let testid = format!("toolbar-text-color-{}", option.id);
|
||||
view! {
|
||||
<button
|
||||
class="toolbar-menu-item toolbar-color-item"
|
||||
data-testid=testid
|
||||
on:click=move |_| {
|
||||
apply_feedback_result(
|
||||
set_command_feedback,
|
||||
apply_text_color(editor, value),
|
||||
);
|
||||
set_color_menu_open.set(false);
|
||||
}
|
||||
>
|
||||
<span
|
||||
class="toolbar-color-chip"
|
||||
style:background=value
|
||||
></span>
|
||||
<strong>{label}</strong>
|
||||
</button>
|
||||
}
|
||||
}).collect_view()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toolbar-popover-section">
|
||||
<div class="toolbar-popover-title">"背景颜色"</div>
|
||||
<div class="toolbar-color-grid">
|
||||
{TOOLBAR_HIGHLIGHT_COLORS.iter().map(|option| {
|
||||
let value = option.value;
|
||||
let label = option.label;
|
||||
let testid = format!("toolbar-highlight-color-{}", option.id);
|
||||
view! {
|
||||
<button
|
||||
class="toolbar-menu-item toolbar-color-item"
|
||||
data-testid=testid
|
||||
on:click=move |_| {
|
||||
apply_feedback_result(
|
||||
set_command_feedback,
|
||||
apply_highlight_color(editor, Some(value)),
|
||||
);
|
||||
set_color_menu_open.set(false);
|
||||
}
|
||||
>
|
||||
<span
|
||||
class="toolbar-color-chip"
|
||||
style:background=value
|
||||
></span>
|
||||
<strong>{label}</strong>
|
||||
</button>
|
||||
}
|
||||
}).collect_view()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toolbar-popover-section">
|
||||
<div
|
||||
class="toolbar-popover-panel"
|
||||
data-testid="toolbar-color-panel"
|
||||
style:display=move || if color_menu_open.get() { "grid" } else { "none" }
|
||||
on:mousedown=move |event: MouseEvent| {
|
||||
event.stop_propagation();
|
||||
}
|
||||
on:click=move |event: MouseEvent| {
|
||||
event.stop_propagation();
|
||||
}
|
||||
on:wheel=move |event: WheelEvent| {
|
||||
trap_scroll_inside_menu(&event);
|
||||
}
|
||||
>
|
||||
<div class="toolbar-popover-section">
|
||||
<div class="toolbar-popover-title">"文字颜色"</div>
|
||||
<div class="toolbar-color-grid">
|
||||
{TOOLBAR_TEXT_COLORS.iter().map(|option| {
|
||||
let value = option.value;
|
||||
let label = option.label;
|
||||
let testid = format!("toolbar-text-color-{}", option.id);
|
||||
view! {
|
||||
<button
|
||||
class="toolbar-menu-item"
|
||||
data-testid="toolbar-clear-color"
|
||||
class="toolbar-menu-item toolbar-color-item"
|
||||
data-testid=testid
|
||||
on:click=move |_| {
|
||||
apply_feedback_result(
|
||||
set_command_feedback,
|
||||
clear_text_color(editor),
|
||||
apply_text_color(editor, value),
|
||||
);
|
||||
let _ = apply_highlight_color(editor, None);
|
||||
set_color_menu_open.set(false);
|
||||
}
|
||||
>
|
||||
<strong>"清除颜色"</strong>
|
||||
<span>"移除文字色与背景色"</span>
|
||||
<span
|
||||
class="toolbar-color-chip"
|
||||
style:background=value
|
||||
></span>
|
||||
<strong>{label}</strong>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}.into_any()
|
||||
} else {
|
||||
().into_any()
|
||||
}
|
||||
}}
|
||||
}
|
||||
}).collect_view()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toolbar-popover-section">
|
||||
<div class="toolbar-popover-title">"背景颜色"</div>
|
||||
<div class="toolbar-color-grid">
|
||||
{TOOLBAR_HIGHLIGHT_COLORS.iter().map(|option| {
|
||||
let value = option.value;
|
||||
let label = option.label;
|
||||
let testid = format!("toolbar-highlight-color-{}", option.id);
|
||||
view! {
|
||||
<button
|
||||
class="toolbar-menu-item toolbar-color-item"
|
||||
data-testid=testid
|
||||
on:click=move |_| {
|
||||
apply_feedback_result(
|
||||
set_command_feedback,
|
||||
apply_highlight_color(editor, Some(value)),
|
||||
);
|
||||
set_color_menu_open.set(false);
|
||||
}
|
||||
>
|
||||
<span
|
||||
class="toolbar-color-chip"
|
||||
style:background=value
|
||||
></span>
|
||||
<strong>{label}</strong>
|
||||
</button>
|
||||
}
|
||||
}).collect_view()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toolbar-popover-section">
|
||||
<button
|
||||
class="toolbar-menu-item"
|
||||
data-testid="toolbar-clear-color"
|
||||
on:click=move |_| {
|
||||
apply_feedback_result(
|
||||
set_command_feedback,
|
||||
clear_text_color(editor),
|
||||
);
|
||||
let _ = apply_highlight_color(editor, None);
|
||||
set_color_menu_open.set(false);
|
||||
}
|
||||
>
|
||||
<strong>"清除颜色"</strong>
|
||||
<span>"移除文字色与背景色"</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3082,69 +3110,66 @@ fn App() -> impl IntoView {
|
||||
|| more_menu_open.get()).to_string()
|
||||
data-testid="toolbar-more"
|
||||
on:click=move |_| {
|
||||
set_more_menu_open.update(|open| *open = !*open);
|
||||
let next_open = !more_menu_open.get_untracked();
|
||||
if next_open {
|
||||
set_locked_toolbar_anchor
|
||||
.set(floating_toolbar_anchor.get_untracked());
|
||||
}
|
||||
set_more_menu_open.set(next_open);
|
||||
set_color_menu_open.set(false);
|
||||
set_turn_into_open.set(false);
|
||||
}
|
||||
>
|
||||
"More"
|
||||
</button>
|
||||
{move || {
|
||||
if more_menu_open.get() {
|
||||
view! {
|
||||
<div
|
||||
class="toolbar-popover-panel"
|
||||
data-testid="toolbar-more-panel"
|
||||
on:mousedown=move |event: MouseEvent| {
|
||||
event.prevent_default();
|
||||
event.stop_propagation();
|
||||
}
|
||||
on:click=move |event: MouseEvent| {
|
||||
event.stop_propagation();
|
||||
}
|
||||
on:wheel=move |event: WheelEvent| {
|
||||
trap_scroll_inside_menu(&event);
|
||||
}
|
||||
>
|
||||
<div class="toolbar-popover-section">
|
||||
<div class="toolbar-popover-title">"对齐方式"</div>
|
||||
<div class="toolbar-more-list">
|
||||
{TOOLBAR_ALIGN_OPTIONS.iter().map(|option| {
|
||||
let label = option.label;
|
||||
let alignment = option.alignment;
|
||||
let testid = format!("toolbar-align-{}", option.id);
|
||||
let active = match option.alignment {
|
||||
TiptapTextAlign::Left => selection_state.get().align_left,
|
||||
TiptapTextAlign::Center => selection_state.get().align_center,
|
||||
TiptapTextAlign::Right => selection_state.get().align_right,
|
||||
TiptapTextAlign::Justify => selection_state.get().align_justify,
|
||||
};
|
||||
view! {
|
||||
<button
|
||||
class="toolbar-menu-item toolbar-more-item"
|
||||
data-active=active.to_string()
|
||||
data-testid=testid
|
||||
on:click=move |_| {
|
||||
apply_feedback_result(
|
||||
set_command_feedback,
|
||||
apply_text_align(editor, alignment),
|
||||
);
|
||||
set_more_menu_open.set(false);
|
||||
}
|
||||
>
|
||||
<strong>{label}</strong>
|
||||
<span>"按官方浮动工具条对当前块对齐"</span>
|
||||
</button>
|
||||
}
|
||||
}).collect_view()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}.into_any()
|
||||
} else {
|
||||
().into_any()
|
||||
<div
|
||||
class="toolbar-popover-panel"
|
||||
data-testid="toolbar-more-panel"
|
||||
style:display=move || if more_menu_open.get() { "grid" } else { "none" }
|
||||
on:mousedown=move |event: MouseEvent| {
|
||||
event.stop_propagation();
|
||||
}
|
||||
}}
|
||||
on:click=move |event: MouseEvent| {
|
||||
event.stop_propagation();
|
||||
}
|
||||
on:wheel=move |event: WheelEvent| {
|
||||
trap_scroll_inside_menu(&event);
|
||||
}
|
||||
>
|
||||
<div class="toolbar-popover-section">
|
||||
<div class="toolbar-popover-title">"对齐方式"</div>
|
||||
<div class="toolbar-more-list">
|
||||
{TOOLBAR_ALIGN_OPTIONS.iter().map(|option| {
|
||||
let label = option.label;
|
||||
let alignment = option.alignment;
|
||||
let testid = format!("toolbar-align-{}", option.id);
|
||||
let active = match option.alignment {
|
||||
TiptapTextAlign::Left => selection_state.get().align_left,
|
||||
TiptapTextAlign::Center => selection_state.get().align_center,
|
||||
TiptapTextAlign::Right => selection_state.get().align_right,
|
||||
TiptapTextAlign::Justify => selection_state.get().align_justify,
|
||||
};
|
||||
view! {
|
||||
<button
|
||||
class="toolbar-menu-item toolbar-more-item"
|
||||
data-active=active.to_string()
|
||||
data-testid=testid
|
||||
on:click=move |_| {
|
||||
apply_feedback_result(
|
||||
set_command_feedback,
|
||||
apply_text_align(editor, alignment),
|
||||
);
|
||||
set_more_menu_open.set(false);
|
||||
}
|
||||
>
|
||||
<strong>{label}</strong>
|
||||
<span>"按官方浮动工具条对当前块对齐"</span>
|
||||
</button>
|
||||
}
|
||||
}).collect_view()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user