snippet.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import {useRef, useState} from "react";
  2. import {connect} from "react-redux";
  3. import {Redirect} from "react-router";
  4. import {useEffect} from "react";
  5. import Editor from "./editor";
  6. import {actionSnippetAdd} from "../actions/actionSnippetAdd";
  7. const Snippets = ({onSave}) => {
  8. const [files, setFiles] = useState([
  9. {type: "html", text:`
  10. <div id='area'>⚠ achtung ⚠</div>
  11. <div>
  12. <button id='greek'>Change color</button>
  13. <button id='bluek'>Change color</button>
  14. </div>`, name:'main.html'},
  15. {type: "css", text:`
  16. @import url(https://fonts.googleapis.com/css?family=Open+Sans);
  17. body {
  18. background: #111;
  19. font-family: 'Open Sans', Impact;
  20. }
  21. #area {
  22. margin-bottom:70px;
  23. text-align: center;
  24. font-size: 6.5em;
  25. color: #fff;
  26. letter-spacing: -7px;
  27. font-weight: 700;
  28. text-transform: uppercase;
  29. animation: blur .75s ease-out infinite;
  30. text-shadow: 0px 0px 5px #fff, 0px 0px 7px #fff;
  31. }
  32. @keyframes blur {
  33. from {
  34. text-shadow:0px 0px 10px #fff,
  35. 0px 0px 10px #fff,
  36. 0px 0px 25px #fff,
  37. 0px 0px 25px #fff,
  38. 0px 0px 25px #fff,
  39. 0px 0px 25px #fff,
  40. 0px 0px 25px #fff,
  41. 0px 0px 25px #fff,
  42. 0px 0px 50px #fff,
  43. 0px 0px 50px #fff,
  44. 0px 0px 50px #7B96B8,
  45. 0px 0px 150px #7B96B8,
  46. 0px 10px 100px #7B96B8,
  47. 0px 10px 100px #7B96B8,
  48. 0px 10px 100px #7B96B8,
  49. 0px 10px 100px #7B96B8,
  50. 0px -10px 100px #7B96B8,
  51. 0px -10px 100px #7B96B8;
  52. }`, name:'style.css'},
  53. {type: "javascript",text:`
  54. greek.style.color='white'
  55. greek.style.background='green'
  56. greek.style.borderRadius='40px'
  57. bluek.style.color='white'
  58. bluek.style.background='blue'
  59. bluek.style.borderRadius='40px'
  60. greek.onclick = () => {
  61. document.getElementById('area').style.color = 'green'
  62. }
  63. bluek.onclick = () => {
  64. document.getElementById('area').style.color = 'blue'
  65. }`,name:'main.js'},
  66. ]);
  67. const [name, setName] = useState("");
  68. const [title, setTitle] = useState("");
  69. const [description, setDescription] = useState("");
  70. const [srcDoc, setSrcDoc] = useState("");
  71. const html = files.filter((elem) => {
  72. return elem?.type === "html";
  73. })[0]?.text;
  74. const css = files.filter((elem) => {
  75. return elem?.type === "css";
  76. })[0]?.text;
  77. const js = files.filter((elem) => {
  78. return elem?.type === "javascript";
  79. })[0]?.text;
  80. useEffect(() => {
  81. const timeout = setTimeout(() => {
  82. setSrcDoc(`
  83. <html>
  84. <body>${html || ""}</body>
  85. <style>${css || ""}</style>
  86. <script>${js || ""}</script>
  87. </html>
  88. `);
  89. }, 250);
  90. return () => clearTimeout(timeout);
  91. }, [html, css, js]);
  92. return (
  93. <div>
  94. <iframe srcDoc={srcDoc} title="output" sandbox="allow-scripts" frameBorder="0" width="95%"
  95. height="100%" style={{height: "280px", marginLeft: "2%",marginTop: "10px", border: "5px solid green"}}/>
  96. {files.map((data, index) => (
  97. <>
  98. <Editor onDelete={() => setFiles(files.filter((item) => item !== data))} data={data}
  99. onChange={({type, name, text}) => setFiles([...files.slice(0, index),{type, name, text},...files.slice(index + 1),])}
  100. />
  101. </>
  102. ))}
  103. <br />
  104. <div style={{alignItems: "center", textAlign: "center", marginTop: "20px", marginBottom: "20px"}}>
  105. <div>
  106. <button className="btn btn-primary" style={{}} onClick={()=> setFiles([...files, { type: "html" }])} key={files} style={{marginTop: "10px"}}>
  107. Add editor
  108. </button>
  109. </div>
  110. <div className="input-group mb-3 mt-5 ml-auto mr-auto w-50">
  111. <div className="input-group-prepend">
  112. <span className="input-group-text" id="basic-addon1">
  113. Name of your project
  114. </span>
  115. </div>
  116. <input value={title} onChange={(e) => setTitle(e.target.value)} type="text" className="form-control"
  117. placeholder="Name of project" aria-label="Name of project" aria-describedby="basic-addon1"/>
  118. </div>
  119. <div className="input-group ml-auto mr-auto w-50">
  120. <div className="input-group-prepend">
  121. <span className="input-group-text ">Description</span>
  122. </div>
  123. <textarea value={description} onChange={(e) => setDescription(e.target.value)} className="form-control "
  124. aria-label="With textarea" placeholder="Your description"></textarea>
  125. </div>
  126. <button className="btn btn-success float-center mr-5 mb-5" onClick={() => onSave(title, description, files)} style={{marginTop: '30px'}}>
  127. Save project
  128. </button>
  129. </div>
  130. </div>
  131. );
  132. };
  133. const CSnippets = connect(null, {onSave: actionSnippetAdd})(Snippets);
  134. export default CSnippets;