snippet.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. import { useRef, useState } from "react";
  2. import { useEffect } from "react";
  3. import React from 'react'
  4. import { connect } from "react-redux";
  5. import { Redirect } from "react-router";
  6. import { render } from 'react-dom';
  7. import Editor from "./editor";
  8. import { actionSnippetAdd } from "../actions/actionSnippetAdd";
  9. import {sortableContainer, sortableElement, arrayMove} from 'react-sortable-hoc';
  10. ///---------------------------------------------------------=------------------
  11. /*
  12. const SortableItem = sortableElement(({value}) => <li>{value}</li>);
  13. const SortableContainer = sortableContainer(({children}) => {
  14. return <ul>{children}</ul>;
  15. });
  16. const Sortable = ({render:Tag}) => {
  17. const [items, setItems] = useState(['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6'])
  18. const onSortEnd = ({oldIndex, newIndex}) => {
  19. let arr = arrayMove(items, oldIndex, newIndex);
  20. for(let i=0; i<arr.length; i++){
  21. arr[i].position = i;
  22. }
  23. setItems(arr)
  24. }
  25. return (
  26. <Tag>
  27. {items.map((value, index) => (
  28. <SortableItem key={`item-${value}`} index={index} value={value} />
  29. ))}
  30. </Tag>
  31. )
  32. }*/
  33. const Snippets = ({onSave}) => {
  34. const [files, setFiles] = useState([
  35. {type: "html", text:`
  36. <div id='area'>⚠ achtung ⚠</div>
  37. <div>
  38. <button id='greek'>Change color</button>
  39. <button id='bluek'>Change color</button>
  40. </div>`, name:'main.html'},
  41. {type: "css", text:`
  42. @import url(https://fonts.googleapis.com/css?family=Open+Sans);
  43. body {
  44. background: #111;
  45. font-family: 'Open Sans', Impact;
  46. }
  47. #area {
  48. margin-bottom:70px;
  49. text-align: center;
  50. font-size: 6.5em;
  51. color: #fff;
  52. letter-spacing: -7px;
  53. font-weight: 700;
  54. text-transform: uppercase;
  55. animation: blur .75s ease-out infinite;
  56. text-shadow: 0px 0px 5px #fff, 0px 0px 7px #fff;
  57. }
  58. @keyframes blur {
  59. from {
  60. text-shadow:0px 0px 10px #fff,
  61. 0px 0px 10px #fff,
  62. 0px 0px 25px #fff,
  63. 0px 0px 25px #fff,
  64. 0px 0px 25px #fff,
  65. 0px 0px 25px #fff,
  66. 0px 0px 25px #fff,
  67. 0px 0px 25px #fff,
  68. 0px 0px 50px #fff,
  69. 0px 0px 50px #fff,
  70. 0px 0px 50px #7B96B8,
  71. 0px 0px 150px #7B96B8,
  72. 0px 10px 100px #7B96B8,
  73. 0px 10px 100px #7B96B8,
  74. 0px 10px 100px #7B96B8,
  75. 0px 10px 100px #7B96B8,
  76. 0px -10px 100px #7B96B8,
  77. 0px -10px 100px #7B96B8;
  78. }`, name:'style.css'},
  79. {type: "javascript",text:`
  80. greek.style.color='white'
  81. greek.style.background='green'
  82. greek.style.borderRadius='40px'
  83. bluek.style.color='white'
  84. bluek.style.background='blue'
  85. bluek.style.borderRadius='40px'
  86. greek.onclick = () => {
  87. document.getElementById('area').style.color = 'green'
  88. }
  89. bluek.onclick = () => {
  90. document.getElementById('area').style.color = 'blue'
  91. }`,name:'main.js'},
  92. ]);
  93. const [name, setName] = useState("");
  94. const [title, setTitle] = useState("");
  95. const [description, setDescription] = useState("");
  96. const [srcDoc, setSrcDoc] = useState("");
  97. const html = files.filter((elem) => {
  98. return elem?.type === "html";
  99. })[0]?.text;
  100. const css = files.filter((elem) => {
  101. return elem?.type === "css";
  102. })[0]?.text;
  103. const js = files.filter((elem) => {
  104. return elem?.type === "javascript";
  105. })[0]?.text;
  106. useEffect(() => {
  107. const timeout = setTimeout(() => {
  108. setSrcDoc(`
  109. <html>
  110. <body>${html || ""}</body>
  111. <style>${css || ""}</style>
  112. <script>${js || ""}</script>
  113. </html>
  114. `);
  115. }, 250);
  116. return () => clearTimeout(timeout);
  117. }, [html, css, js]);
  118. const [click, setClick] = useState(false)
  119. const SortableItem = sortableElement(({value, index}) => {
  120. return (
  121. <span><ins>{value.name || "new edit "}</ins> &nbsp; </span>
  122. )
  123. })
  124. const SortableList = sortableContainer(({items})=>{
  125. return(
  126. <div>
  127. {items?.map((value, index) => (
  128. <SortableItem value={value} index={index} />
  129. ))
  130. }
  131. </div>
  132. )
  133. })
  134. const onSortEnd = ({oldIndex, newIndex}) => {
  135. let arr = arrayMove(files, oldIndex, newIndex);
  136. setFiles(arr)
  137. }
  138. return (
  139. <div>
  140. <iframe srcDoc={srcDoc} title="output"
  141. sandbox="allow-scripts" frameBorder="0" width="95%"
  142. height="100%"
  143. style={{height: "280px", marginLeft: "2%",marginTop: "10px", border: "5px solid green"}}/>
  144. <br/>
  145. <div style={{marginTop:"20px", textAlign:'center'}}>
  146. <p><b>Click here </b><span>to reverse the snippets</span></p>
  147. <SortableList items={files} onSortEnd={onSortEnd} />
  148. </div>
  149. {files.map((data, index) => (
  150. <>
  151. <Editor onDelete={() => setFiles(files.filter((item) => item !== data))} data={data}
  152. onChange={({type, name, text}) => setFiles([...files.slice(0, index),{type, name, text},...files.slice(index + 1),] )}
  153. />
  154. </>
  155. ))}
  156. <br />
  157. <div style={{alignItems: "center", textAlign: "center", marginTop: "20px", marginBottom: "20px"}}>
  158. <div>
  159. <button className="btn btn-primary"
  160. onClick={() => setFiles([...files, { type: "html" }])}
  161. key={files}
  162. style={{marginTop: "10px"}}>
  163. Add editor
  164. </button>
  165. </div>
  166. <div className="input-group mb-3 mt-5 ml-auto mr-auto w-50">
  167. <div className="input-group-prepend">
  168. <span className="input-group-text" id="basic-addon1">
  169. Name of your project
  170. </span>
  171. </div>
  172. <input value={title} onChange={(e) => setTitle(e.target.value)} type="text" className="form-control"
  173. placeholder="Name of project" aria-label="Name of project" aria-describedby="basic-addon1"/>
  174. </div>
  175. <div className="input-group ml-auto mr-auto w-50">
  176. <div className="input-group-prepend">
  177. <span className="input-group-text ">Description</span>
  178. </div>
  179. <textarea className="form-control"
  180. value={description}
  181. onChange={(e) => setDescription(e.target.value)}
  182. aria-label="With textarea"
  183. placeholder="Your description">
  184. </textarea>
  185. </div>
  186. <button className="btn btn-success float-center mr-5 mb-5"
  187. onClick={() => onSave(title, description, files)} style={{marginTop: '30px'}}>
  188. Save project
  189. </button>
  190. </div>
  191. </div>
  192. );
  193. };
  194. const CSnippets = connect(null, {onSave: actionSnippetAdd})(Snippets);
  195. export default CSnippets;