1+ """A Rich Text Editor based on SunEditor."""
2+
3+ from __future__ import annotations
4+
5+ import enum
6+ from typing import Dict , List , Literal , Optional , Union
7+
8+ from reflex .base import Base
9+ from reflex .components .component import Component , NoSSRComponent
10+ from reflex .event import EventHandler
11+ from reflex .utils .format import to_camel_case
12+ from reflex .utils .imports import ImportDict , ImportVar
13+ from reflex .vars .base import Var
14+
15+
16+ class EditorButtonList (list , enum .Enum ):
17+ """List enum that provides three predefined button lists."""
18+
19+ BASIC = [
20+ ["font" , "fontSize" ],
21+ ["fontColor" ],
22+ ["horizontalRule" ],
23+ ["link" , "image" ],
24+ ]
25+ FORMATTING = [
26+ ["undo" , "redo" ],
27+ ["bold" , "underline" , "italic" , "strike" , "subscript" , "superscript" ],
28+ ["removeFormat" ],
29+ ["outdent" , "indent" ],
30+ ["fullScreen" , "showBlocks" , "codeView" ],
31+ ["preview" , "print" ],
32+ ]
33+ COMPLEX = [
34+ ["undo" , "redo" ],
35+ ["font" , "fontSize" , "formatBlock" ],
36+ ["bold" , "underline" , "italic" , "strike" , "subscript" , "superscript" ],
37+ ["removeFormat" ],
38+ "/" ,
39+ ["fontColor" , "hiliteColor" ],
40+ ["outdent" , "indent" ],
41+ ["align" , "horizontalRule" , "list" , "table" ],
42+ ["link" , "image" , "video" ],
43+ ["fullScreen" , "showBlocks" , "codeView" ],
44+ ["preview" , "print" ],
45+ ["save" , "template" ],
46+ ]
47+
48+
49+ class EditorOptions (Base ):
50+ """Some of the additional options to configure the Editor.
51+ Complete list of options found here:
52+ https://github.com/JiHong88/SunEditor/blob/master/README.md#options.
53+ """
54+
55+ # Specifies default tag name of the editor.
56+ # default: 'p' {String}
57+ default_tag : Optional [str ] = None
58+
59+ # The mode of the editor ('classic', 'inline', 'balloon', 'balloon-always').
60+ # default: 'classic' {String}
61+ mode : Optional [str ] = None
62+
63+ # If true, the editor is set to RTL(Right To Left) mode.
64+ # default: false {Boolean}
65+ rtl : Optional [bool ] = None
66+
67+ # List of buttons to use in the toolbar.
68+ button_list : Optional [List [Union [List [str ], str ]]]
69+
70+
71+ class Editor (NoSSRComponent ):
72+ """A Rich Text Editor component based on SunEditor.
73+ Not every JS prop is listed here (some are not easily usable from python),
74+ refer to the library docs for a complete list.
75+ """
76+
77+ library = "suneditor-react"
78+
79+ tag = "SunEditor"
80+
81+ is_default = True
82+
83+ lib_dependencies : List [str ] = ["suneditor" ]
84+
85+ # Language of the editor.
86+ # Alternatively to a string, a dict of your language can be passed to this prop.
87+ # Please refer to the library docs for this.
88+ # options: "en" | "da" | "de" | "es" | "fr" | "ja" | "ko" | "pt_br" |
89+ # "ru" | "zh_cn" | "ro" | "pl" | "ckb" | "lv" | "se" | "ua" | "he" | "it"
90+ # default : "en"
91+ lang : Var [
92+ Union [
93+ Literal [
94+ "en" ,
95+ "da" ,
96+ "de" ,
97+ "es" ,
98+ "fr" ,
99+ "ja" ,
100+ "ko" ,
101+ "pt_br" ,
102+ "ru" ,
103+ "zh_cn" ,
104+ "ro" ,
105+ "pl" ,
106+ "ckb" ,
107+ "lv" ,
108+ "se" ,
109+ "ua" ,
110+ "he" ,
111+ "it" ,
112+ ],
113+ dict ,
114+ ]
115+ ]
116+
117+ # This is used to set the HTML form name of the editor.
118+ # This means on HTML form submission,
119+ # it will be submitted together with contents of the editor by the name provided.
120+ name : Var [str ]
121+
122+ # Sets the default value of the editor.
123+ # This is useful if you don't want the on_change method to be called on render.
124+ # If you want the on_change method to be called on render please use the set_contents prop
125+ default_value : Var [str ]
126+
127+ # Sets the width of the editor.
128+ # px and percentage values are accepted, eg width="100%" or width="500px"
129+ # default: 100%
130+ width : Var [str ]
131+
132+ # Sets the height of the editor.
133+ # px and percentage values are accepted, eg height="100%" or height="100px"
134+ height : Var [str ]
135+
136+ # Sets the placeholder of the editor.
137+ placeholder : Var [str ]
138+
139+ # Should the editor receive focus when initialized?
140+ auto_focus : Var [bool ]
141+
142+ # Pass an EditorOptions instance to modify the behaviour of Editor even more.
143+ set_options : Var [Dict ]
144+
145+ # Whether all SunEditor plugins should be loaded.
146+ # default: True
147+ set_all_plugins : Var [bool ]
148+
149+ # Set the content of the editor.
150+ # Note: To set the initial contents of the editor
151+ # without calling the on_change event,
152+ # please use the default_value prop.
153+ # set_contents is used to set the contents of the editor programmatically.
154+ # You must be aware that, when the set_contents's prop changes,
155+ # the on_change event is triggered.
156+ set_contents : Var [str ]
157+
158+ # Append editor content
159+ append_contents : Var [str ]
160+
161+ # Sets the default style of the editor's edit area
162+ set_default_style : Var [str ]
163+
164+ # Disable the editor
165+ # default: False
166+ disable : Var [bool ]
167+
168+ # Hide the editor
169+ # default: False
170+ hide : Var [bool ]
171+
172+ # Hide the editor toolbar
173+ # default: False
174+ hide_toolbar : Var [bool ]
175+
176+ # Disable the editor toolbar
177+ # default: False
178+ disable_toolbar : Var [bool ]
179+
180+ # Fired when the editor content changes.
181+ on_change : EventHandler [lambda content : [content ]]
182+
183+ # Fired when the something is inputted in the editor.
184+ on_input : EventHandler [lambda e : [e ]]
185+
186+ # Fired when the editor loses focus.
187+ on_blur : EventHandler [lambda e , content : [content ]]
188+
189+ # Fired when the editor is loaded.
190+ on_load : EventHandler [lambda reload : [reload ]]
191+
192+ # Fired when the editor is resized.
193+ on_resize_editor : EventHandler [lambda height , prev_height : [height , prev_height ]]
194+
195+ # Fired when the editor content is copied.
196+ on_copy : EventHandler [lambda e , clipboard_data : [clipboard_data ]]
197+
198+ # Fired when the editor content is cut.
199+ on_cut : EventHandler [lambda e , clipboard_data : [clipboard_data ]]
200+
201+ # Fired when the editor content is pasted.
202+ on_paste : EventHandler [
203+ lambda e , clean_data , max_char_count : [clean_data , max_char_count ]
204+ ]
205+
206+ # Fired when the code view is toggled.
207+ toggle_code_view : EventHandler [lambda is_code_view : [is_code_view ]]
208+
209+ # Fired when the full screen mode is toggled.
210+ toggle_full_screen : EventHandler [lambda is_full_screen : [is_full_screen ]]
211+
212+ def add_imports (self ) -> ImportDict :
213+ """Add imports for the Editor component.
214+
215+ Returns:
216+ The import dict.
217+ """
218+ return {
219+ "" : ImportVar (tag = "suneditor/dist/css/suneditor.min.css" , install = False )
220+ }
221+
222+ @classmethod
223+ def create (cls , set_options : Optional [EditorOptions ] = None , ** props ) -> Component :
224+ """Create an instance of Editor. No children allowed.
225+
226+ Args:
227+ set_options(Optional[EditorOptions]): Configuration object to further configure the instance.
228+ **props: Any properties to be passed to the Editor
229+
230+ Returns:
231+ An Editor instance.
232+
233+ Raises:
234+ ValueError: If set_options is a state Var.
235+ """
236+ if set_options is not None :
237+ if isinstance (set_options , Var ):
238+ raise ValueError ("EditorOptions cannot be a state Var" )
239+ props ["set_options" ] = {
240+ to_camel_case (k ): v
241+ for k , v in set_options .dict ().items ()
242+ if v is not None
243+ }
244+ return super ().create (* [], ** props )
0 commit comments