123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- """A Rich Text Editor based on SunEditor."""
- from __future__ import annotations
- import enum
- from typing import Any, Dict, List, Literal, Optional, Union
- from reflex.base import Base
- from reflex.components.component import Component, NoSSRComponent
- from reflex.constants import EventTriggers
- from reflex.utils.format import to_camel_case
- from reflex.utils.imports import ImportVar
- from reflex.vars import Var
- class EditorButtonList(list, enum.Enum):
- """List enum that provides three predefined button lists."""
- BASIC = [
- ["font", "fontSize"],
- ["fontColor"],
- ["horizontalRule"],
- ["link", "image"],
- ]
- FORMATTING = [
- ["undo", "redo"],
- ["bold", "underline", "italic", "strike", "subscript", "superscript"],
- ["removeFormat"],
- ["outdent", "indent"],
- ["fullScreen", "showBlocks", "codeView"],
- ["preview", "print"],
- ]
- COMPLEX = [
- ["undo", "redo"],
- ["font", "fontSize", "formatBlock"],
- ["bold", "underline", "italic", "strike", "subscript", "superscript"],
- ["removeFormat"],
- "/",
- ["fontColor", "hiliteColor"],
- ["outdent", "indent"],
- ["align", "horizontalRule", "list", "table"],
- ["link", "image", "video"],
- ["fullScreen", "showBlocks", "codeView"],
- ["preview", "print"],
- ["save", "template"],
- ]
- class EditorOptions(Base):
- """Some of the additional options to configure the Editor.
- Complete list of options found here:
- https://github.com/JiHong88/SunEditor/blob/master/README.md#options.
- """
- # Specifies default tag name of the editor.
- # default: 'p' {String}
- default_tag: Optional[str] = None
- # The mode of the editor ('classic', 'inline', 'balloon', 'balloon-always').
- # default: 'classic' {String}
- mode: Optional[str] = None
- # If true, the editor is set to RTL(Right To Left) mode.
- # default: false {Boolean}
- rtl: Optional[bool] = None
- # List of buttons to use in the toolbar.
- button_list: Optional[List[Union[List[str], str]]]
- class Editor(NoSSRComponent):
- """A Rich Text Editor component based on SunEditor.
- Not every JS prop is listed here (some are not easily usable from python),
- refer to the library docs for a complete list.
- """
- library = "suneditor-react"
- tag: str = "SunEditor"
- is_default: bool = True
- lib_dependencies: List[str] = ["suneditor"]
- # Language of the editor.
- # Alternatively to a string, a dict of your language can be passed to this prop.
- # Please refer to the library docs for this.
- # options: "en" | "da" | "de" | "es" | "fr" | "ja" | "ko" | "pt_br" |
- # "ru" | "zh_cn" | "ro" | "pl" | "ckb" | "lv" | "se" | "ua" | "he" | "it"
- # default : "en"
- lang: Var[
- Union[
- Literal[
- "en",
- "da",
- "de",
- "es",
- "fr",
- "ja",
- "ko",
- "pt_br",
- "ru",
- "zh_cn",
- "ro",
- "pl",
- "ckb",
- "lv",
- "se",
- "ua",
- "he",
- "it",
- ],
- dict,
- ]
- ]
- # This is used to set the HTML form name of the editor.
- # This means on HTML form submission,
- # it will be submitted together with contents of the editor by the name provided.
- name: Optional[Var[str]] = None
- # Sets the default value of the editor.
- # This is useful if you don't want the on_change method to be called on render.
- # If you want the on_change method to be called on render please use the set_contents prop
- default_value: Optional[Var[str]] = None
- # Sets the width of the editor.
- # px and percentage values are accepted, eg width="100%" or width="500px"
- # default: 100%
- width: Optional[Var[str]] = None
- # Sets the height of the editor.
- # px and percentage values are accepted, eg height="100%" or height="100px"
- height: Optional[Var[str]] = None
- # Sets the placeholder of the editor.
- placeholder: Optional[Var[str]] = None
- # Should the editor receive focus when initialized?
- auto_focus: Optional[Var[bool]] = None
- # Pass an EditorOptions instance to modify the behaviour of Editor even more.
- set_options: Optional[Var[Dict]] = None
- # Whether all SunEditor plugins should be loaded.
- # default: True
- set_all_plugins: Optional[Var[bool]] = None
- # Set the content of the editor.
- # Note: To set the initial contents of the editor
- # without calling the on_change event,
- # please use the default_value prop.
- # set_contents is used to set the contents of the editor programmatically.
- # You must be aware that, when the set_contents's prop changes,
- # the on_change event is triggered.
- set_contents: Optional[Var[str]] = None
- # Append editor content
- append_contents: Optional[Var[str]] = None
- # Sets the default style of the editor's edit area
- set_default_style: Optional[Var[str]] = None
- # Disable the editor
- # default: False
- disable: Optional[Var[bool]] = None
- # Hide the editor
- # default: False
- hide: Optional[Var[bool]] = None
- # Hide the editor toolbar
- # default: False
- hide_toolbar: Optional[Var[bool]] = None
- # Disable the editor toolbar
- # default: False
- disable_toolbar: Optional[Var[bool]] = None
- def _get_imports(self):
- imports = super()._get_imports()
- imports[""] = [
- ImportVar(tag="suneditor/dist/css/suneditor.min.css", install=False)
- ]
- return imports
- def get_event_triggers(self) -> Dict[str, Any]:
- """Get the event triggers that pass the component's value to the handler.
- Returns:
- A dict mapping the event trigger to the var that is passed to the handler.
- """
- return {
- **super().get_event_triggers(),
- EventTriggers.ON_CHANGE: lambda content: [content],
- "on_input": lambda _e: [_e],
- EventTriggers.ON_BLUR: lambda _e, content: [content],
- "on_load": lambda reload: [reload],
- "on_resize_editor": lambda height, prev_height: [height, prev_height],
- "on_copy": lambda _e, clipboard_data: [clipboard_data],
- "on_cut": lambda _e, clipboard_data: [clipboard_data],
- "on_paste": lambda _e, clean_data, max_char_count: [
- clean_data,
- max_char_count,
- ],
- "toggle_code_view": lambda is_code_view: [is_code_view],
- "toggle_full_screen": lambda is_full_screen: [is_full_screen],
- }
- @classmethod
- def create(cls, set_options: Optional[EditorOptions] = None, **props) -> Component:
- """Create an instance of Editor. No children allowed.
- Args:
- set_options(Optional[EditorOptions]): Configuration object to further configure the instance.
- **props: Any properties to be passed to the Editor
- Returns:
- An Editor instance.
- Raises:
- ValueError: If set_options is a state Var.
- """
- if set_options is not None:
- if isinstance(set_options, Var):
- raise ValueError("EditorOptions cannot be a state Var")
- props["set_options"] = {
- to_camel_case(k): v
- for k, v in set_options.model_dump().items()
- if v is not None
- }
- return super().create(*[], **props)
|