1- import  {  useEffect  }  from  "react" ; 
1+ import  {  useEffect ,   useState  }  from  "react" ; 
22import  {  useStore  }  from  "@nanostores/react" ; 
33import  {  ContentEditable  }  from  "@lexical/react/LexicalContentEditable" ; 
44import  type  {  StoryFn ,  Meta  }  from  "@storybook/react" ; 
55import  {  action  }  from  "@storybook/addon-actions" ; 
6- import  {  Box  }  from  "@webstudio-is/design-system" ; 
6+ import  {  Box ,   Button ,   Flex  }  from  "@webstudio-is/design-system" ; 
77import  {  theme  }  from  "@webstudio-is/design-system" ; 
88import  type  {  Instance ,  Instances  }  from  "@webstudio-is/sdk" ; 
9- import  {  $textToolbar  }  from  "~/shared/nano-states" ; 
9+ import  { 
10+   $instances , 
11+   $pages , 
12+   $registeredComponentMetas , 
13+   $selectedPageId , 
14+   $textEditingInstanceSelector , 
15+   $textToolbar , 
16+ }  from  "~/shared/nano-states" ; 
1017import  {  TextEditor  }  from  "./text-editor" ; 
1118import  {  emitCommand ,  subscribeCommands  }  from  "~/canvas/shared/commands" ; 
19+ import  {  $ ,  renderJsx  }  from  "@webstudio-is/sdk/testing" ; 
1220
1321export  default  { 
1422  component : TextEditor , 
@@ -33,17 +41,21 @@ const createInstancePair = (
3341
3442const  instances : Instances  =  new  Map ( [ 
3543  createInstancePair ( "1" ,  "Text" ,  [ 
36-     {  type : "text" ,  value : "Paragraph you can edit "  } , 
44+     {  type : "text" ,  value : "Paragraph you can edit Blabla  "  } , 
3745    {  type : "id" ,  value : "2"  } , 
3846    {  type : "id" ,  value : "3"  } , 
3947    {  type : "id" ,  value : "5"  } , 
4048  ] ) , 
41-   createInstancePair ( "2" ,  "Bold" ,  [ {  type : "text" ,  value : "very bold text "  } ] ) , 
49+   createInstancePair ( "2" ,  "Bold" ,  [ 
50+     {  type : "text" ,  value : "Very Very very bold text "  } , 
51+   ] ) , 
4252  createInstancePair ( "3" ,  "Bold" ,  [ {  type : "id" ,  value : "4"  } ] ) , 
4353  createInstancePair ( "4" ,  "Italic" ,  [ 
44-     {  type : "text" ,  value : "with small italic"  } , 
54+     {  type : "text" ,  value : "And Bold Small with small italic"  } , 
55+   ] ) , 
56+   createInstancePair ( "5" ,  "Bold" ,  [ 
57+     {  type : "text" ,  value : " la la la subtext"  } , 
4558  ] ) , 
46-   createInstancePair ( "5" ,  "Bold" ,  [ {  type : "text" ,  value : " subtext"  } ] ) , 
4759] ) ; 
4860
4961export  const  Basic : StoryFn < typeof  TextEditor >  =  ( {  onChange } )  =>  { 
@@ -128,6 +140,229 @@ export const Basic: StoryFn<typeof TextEditor> = ({ onChange }) => {
128140  ) ; 
129141} ; 
130142
143+ export  const  CursorPositioning : StoryFn < typeof  TextEditor >  =  ( {  onChange } )  =>  { 
144+   const  textEditingInstanceSelector  =  useStore ( $textEditingInstanceSelector ) ; 
145+ 
146+   return  ( 
147+     < > 
148+       < Box 
149+         css = { { 
150+           width : 300 , 
151+           "& > div" : { 
152+             padding : 40 , 
153+             backgroundColor : textEditingInstanceSelector 
154+               ? "unset" 
155+               : "rgba(0,0,0,0.1)" , 
156+           } , 
157+           border : "1px solid #999" , 
158+           color : "black" , 
159+           " *" : { 
160+             outline : "none" , 
161+           } , 
162+         } } 
163+         onClick = { ( event )  =>  { 
164+           if  ( textEditingInstanceSelector  !==  undefined )  { 
165+             return ; 
166+           } 
167+           $textEditingInstanceSelector . set ( { 
168+             selector : [ "1" ] , 
169+             reason : "click" , 
170+             mouseX : event . clientX , 
171+             mouseY : event . clientY , 
172+           } ) ; 
173+         } } 
174+       > 
175+         { textEditingInstanceSelector  &&  ( 
176+           < TextEditor 
177+             rootInstanceSelector = { [ "1" ] } 
178+             instances = { instances } 
179+             contentEditable = { < ContentEditable  /> } 
180+             onChange = { onChange } 
181+             onSelectInstance = { ( instanceId )  => 
182+               console . info ( "select instance" ,  instanceId ) 
183+             } 
184+           /> 
185+         ) } 
186+ 
187+         { ! textEditingInstanceSelector  &&  ( 
188+           < div > 
189+             < span > Paragraph you can edit Blabla </ span > 
190+             < strong > Very Very very bold text </ strong > 
191+             < strong > 
192+               < i > And Bold Small with small italic</ i > 
193+             </ strong > 
194+             < strong >  la la la subtext</ strong > 
195+           </ div > 
196+         ) } 
197+       </ Box > 
198+       < br  /> 
199+       < div > 
200+         < i > Click on text above, see cursor position and start editing text</ i > 
201+       </ div > 
202+       { textEditingInstanceSelector  &&  ( 
203+         < Button 
204+           onClick = { ( )  =>  { 
205+             $textEditingInstanceSelector . set ( undefined ) ; 
206+           } } 
207+         > 
208+           Reset
209+         </ Button > 
210+       ) } 
211+     </ > 
212+   ) ; 
213+ } ; 
214+ 
215+ export  const  CursorPositioningUpDown : StoryFn < typeof  TextEditor >  =  ( )  =>  { 
216+   const  [ {  instances } ,  setState ]  =  useState ( ( )  =>  { 
217+     $pages . set ( { 
218+       folders : [ ] , 
219+       homePage : { 
220+         id : "homePageId" , 
221+         rootInstanceId : "bodyId" , 
222+         meta : { } , 
223+         path : "" , 
224+         title : "" , 
225+         name : "" , 
226+         systemDataSourceId : "" , 
227+       } , 
228+       pages : [ 
229+         { 
230+           id : "pageId" , 
231+           rootInstanceId : "bodyId" , 
232+           path : "" , 
233+           title : "" , 
234+           name : "" , 
235+           systemDataSourceId : "" , 
236+           meta : { } , 
237+         } , 
238+       ] , 
239+     } ) ; 
240+ 
241+     $selectedPageId . set ( "pageId" ) ; 
242+ 
243+     $registeredComponentMetas . set ( 
244+       new  Map ( [ 
245+         [ 
246+           "Box" , 
247+           { 
248+             type : "container" , 
249+             icon : "icon" , 
250+           } , 
251+         ] , 
252+         [ 
253+           "Bold" , 
254+           { 
255+             type : "rich-text-child" , 
256+             icon : "icon" , 
257+           } , 
258+         ] , 
259+       ] ) 
260+     ) ; 
261+ 
262+     return  renderJsx ( 
263+       < $ . Body  ws :id = "bodyId" > 
264+         < $ . Box  ws :id = "boxAId" > 
265+           Hello world < $ . Bold  ws :id = "boldA" > Hello world</ $ . Bold >  Hello world
266+           world Hello worldsdsdj skdk ls dk jslkdjklsjdkl sdk jskdj ksjd lksdj
267+           dsj
268+         </ $ . Box > 
269+         < $ . Box  ws :id = "boxBId" > 
270+           Let it be Let it be < $ . Bold  ws :id = "boldB" > Let it be Let</ $ . Bold >  Let
271+           it be Let it be Let it be Let it be Let it be Let it be
272+         </ $ . Box > 
273+       </ $ . Body > 
274+     ) ; 
275+   } ) ; 
276+ 
277+   useEffect ( ( )  =>  { 
278+     $instances . set ( instances ) ; 
279+   } ,  [ instances ] ) ; 
280+ 
281+   const  textEditingInstanceSelector  =  useStore ( $textEditingInstanceSelector ) ; 
282+ 
283+   return  ( 
284+     < > 
285+       < Flex 
286+         gap = { 2 } 
287+         direction = { "column" } 
288+         css = { { 
289+           width : 500 , 
290+           "& > div > div" : { 
291+             padding : 5 , 
292+             border : "1px solid #999" , 
293+           } , 
294+           "& *[aria-readonly]" : { 
295+             backgroundColor : "rgba(0,0,0,0.02)" , 
296+           } , 
297+           "& strong" : { 
298+             fontSize : "1.5em" , 
299+           } , 
300+ 
301+           color : "black" , 
302+           " *" : { 
303+             outline : "none" , 
304+           } , 
305+         } } 
306+       > 
307+         < div  style = { {  display : "contents"  } }  data-ws-selector = "boxAId,bodyId" > 
308+           < TextEditor 
309+             key = { textEditingInstanceSelector ?. selector [ 0 ]  ??  "" } 
310+             editable = { 
311+               textEditingInstanceSelector  ===  undefined  || 
312+               textEditingInstanceSelector ?. selector [ 0 ]  ===  "boxAId" 
313+             } 
314+             rootInstanceSelector = { [ "boxAId" ,  "bodyId" ] } 
315+             instances = { instances } 
316+             contentEditable = { < ContentEditable  /> } 
317+             onChange = { ( data )  =>  { 
318+               setState ( ( prev )  =>  { 
319+                 for  ( const  instance  of  data )  { 
320+                   prev . instances . set ( instance . id ,  instance ) ; 
321+                 } 
322+                 return  prev ; 
323+               } ) ; 
324+             } } 
325+             onSelectInstance = { ( instanceId )  => 
326+               console . info ( "select instance" ,  instanceId ) 
327+             } 
328+           /> 
329+         </ div > 
330+ 
331+         < div 
332+           style = { {  display : "contents"  } } 
333+           data-ws-selector = "boxBId,bodyId" 
334+           data-ws-collapsed = "true" 
335+         > 
336+           < TextEditor 
337+             key = { textEditingInstanceSelector ?. selector [ 0 ]  ??  "" } 
338+             editable = { textEditingInstanceSelector ?. selector [ 0 ]  ===  "boxBId" } 
339+             rootInstanceSelector = { [ "boxBId" ,  "bodyId" ] } 
340+             instances = { instances } 
341+             contentEditable = { < ContentEditable  /> } 
342+             onChange = { ( data )  =>  { 
343+               setState ( ( prev )  =>  { 
344+                 for  ( const  instance  of  data )  { 
345+                   prev . instances . set ( instance . id ,  instance ) ; 
346+                 } 
347+                 return  prev ; 
348+               } ) ; 
349+             } } 
350+             onSelectInstance = { ( instanceId )  => 
351+               console . info ( "select instance" ,  instanceId ) 
352+             } 
353+           /> 
354+         </ div > 
355+       </ Flex > 
356+       < br  /> 
357+       < i > Use arrows to move between editors, clicks are not working</ i > 
358+     </ > 
359+   ) ; 
360+ } ; 
361+ 
131362Basic . args  =  { 
132363  onChange : action ( "onChange" ) , 
133364} ; 
365+ 
366+ CursorPositioning . args  =  { 
367+   onChange : action ( "onChange" ) , 
368+ } ; 
0 commit comments