edit.html 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Contract Generator</title>
  8. <base href="./">
  9. <link rel="shortcut icon" type="image/x-icon" href="favicon/favicon.ico" />
  10. <link rel="apple-touch-icon" sizes="180x180" href="favicon/apple-touch-icon.png">
  11. <link rel="icon" type="image/png" sizes="32x32" href="favicon/favicon-32x32.png">
  12. <link rel="icon" type="image/png" sizes="16x16" href="favicon/favicon-16x16.png">
  13. <link rel="manifest" href="favicon/site.webmanifest">
  14. <link rel="preconnect" href="https://cdn.skypack.dev">
  15. <link rel="preconnect" href="https://fonts.gstatic.com">
  16. <link rel="preconnect" href="https://fonts.googleapis.com">
  17. <link rel="stylesheet" href="styles/main.css">
  18. <!-- <link rel="stylesheet" href="styles/style.min.css"> -->
  19. <link rel="stylesheet" href="styles/highlight.min.css" />
  20. <script src="scripts/highlight/highlight.min.js" defer></script>
  21. <script charset="UTF-8" src="scripts/highlight/xml.min.js" defer></script>
  22. <script src="scripts/main.js" type="module"></script>
  23. </head>
  24. <body>
  25. <a class="skip-to-content button" href="#main">Skip to contract content</a>
  26. <a class="skip-to-content button" href="#below-contract">Skip to signature</a>
  27. <main id="wysiwyg-wrap" class="w-medium flex-1">
  28. <!-- Toolbar -->
  29. <div title="Toolbar" id="toolbar-wrap" class="animate fade">
  30. <div id="toolbar">
  31. <button title="Scroll down" type="button"
  32. onclick="document.querySelector('#below-contract').scrollIntoView()">
  33. <svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 1024 1024" height="1em"
  34. width="1em" xmlns="http://www.w3.org/2000/svg">
  35. <use href="#down-circle"></use>
  36. </svg>
  37. </button>
  38. <!-- Bold, italic, and underline buttons -->
  39. <span class="ql-formats">
  40. <button aria-label="Bold" type="button" class="ql-bold"></button>
  41. <button aria-label="Italic" type="button" class="ql-italic"></button>
  42. <button aria-label="Underline" type="button" class="ql-underline"></button>
  43. </span>
  44. <!-- Headings dropdown -->
  45. <span class="ql-formats">
  46. <select aria-label="Heading" class="ql-header" style="margin-inline-end: .5rem;">
  47. <option aria-label="Normal" selected></option>
  48. <option aria-label="Heading 1" value="1"></option>
  49. <option aria-label="Heading 2" value="2"></option>
  50. <option aria-label="Heading 3" value="3"></option>
  51. </select>
  52. <!-- <select aria-label="Align" class="ql-align">
  53. <option aria-label="Left" selected></option>
  54. <option aria-label="Center" value="center"></option>
  55. <option aria-label="Right" value="right"></option>
  56. <option aria-label="Justify" value="justify"></option>
  57. </select> -->
  58. </span>
  59. <!-- Align buttons -->
  60. <span class="ql-formats">
  61. <button aria-label="Align Left" type="button" class="ql-align" value=""></button>
  62. <button aria-label="Align Center" type="button" class="ql-align" value="center"></button>
  63. <button aria-label="Align Right" type="button" class="ql-align" value="right"></button>
  64. <button aria-label="Align Justify" type="button" class="ql-align" value="justify"></button>
  65. </span>
  66. <!-- Subscript and superscript buttons -->
  67. <span class="ql-formats">
  68. <button type="button" class="ql-script" value="sub"></button>
  69. <button type="button" class="ql-script" value="super"></button>
  70. </span>
  71. <!-- Clean button -->
  72. <span class="ql-formats">
  73. <button aria-label="Clean formatting" type="button" class="ql-clean"></button>
  74. </span>
  75. <!-- https://codepen.io/nonsalant/pen/YzvBNNg/e0bc9e0853f4de48c02256e5d5de7441https://codepen.io/nonsalant/pen/YzvBNNg/e0bc9e0853f4de48c02256e5d5de7441 -->
  76. <!-- <button class="ql-html">HTML</button> -->
  77. <span class="ql-formats">
  78. <button aria-label="Ordered list" type="button" class="ql-list" value="ordered"></button>
  79. <button aria-label="Bullet list" type="button" class="ql-list" value="bullet"></button>
  80. </span>
  81. <span class="ql-formats">
  82. <button aria-label="Indent +1" type="button" class="ql-indent" value="-1"></button>
  83. <button aria-label="Indent -1" type="button" class="ql-indent" value="+1"></button>
  84. </span>
  85. <span class="ql-formats">
  86. <button title="Insert an image" type="button" class="ql-image"></button>
  87. </span>
  88. </div>
  89. </div>
  90. <!-- Editor -->
  91. <div id="main" class="editor-container | animate slide">
  92. <div
  93. style="padding-inline: clamp(20px,5vw,35px); padding-block-start: 2.5rem; color: var(--clr-green-desaturated-500);">
  94. Loading contract…
  95. </div>
  96. </div>
  97. </main>
  98. <footer class="below-contract flow | animate fade delay-3">
  99. <div id="below-contract" class="signature-area w-medium padding-clamp">
  100. <div id="signature-container">
  101. <!-- Signature -->
  102. <div id="canvas-container">
  103. <canvas aria-label="Input signature" id="generator-signature-pad" class="signature-pad" width="188"
  104. height="58.66"></canvas>
  105. </div>
  106. <!-- Action Buttons -->
  107. <div id="signature-controls">
  108. <div class="flexi">
  109. <button id="clear-signature" type="button" class="button warning">
  110. <span>Clear <span class="hide-small">signature</span></span>
  111. <span class="icon">
  112. <svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24"
  113. height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">
  114. <use href="#icon-erase"></use>
  115. </svg>
  116. </span>
  117. </button>
  118. <button id="show-modal-preview" type="button" class="button success preview">
  119. <span>Preview <span class="hide-small">as Client</span></span>
  120. <span class="icon">
  121. <svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 1024 1024"
  122. height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">
  123. <use href="#icon-preview"></use>
  124. </svg>
  125. </span>
  126. </button>
  127. <!-- <button id="show-modal-qr" type="button" class="open-button | button"
  128. title="Show QR: scan this code to open the page on another device">
  129. <span class="icon small-padding">
  130. <svg stroke="currentColor" fill="currentColor" stroke-width="0" version="1.1"
  131. viewBox="0 0 16 16" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">
  132. <use href="#icon-qr"></use>
  133. </svg>
  134. </span>
  135. </button> -->
  136. </div>
  137. </div>
  138. </div>
  139. </div>
  140. <div class="generator-options flow padding-clamp w-medium">
  141. <div class="generator-main-options flow">
  142. <h3>Optional Contract Settings</h3>
  143. <!-- Name fields -->
  144. <details class="animate slide delay-1">
  145. <summary>
  146. Names
  147. </summary>
  148. <form class="panel flexi">
  149. <p class="grid">
  150. <label for="dev_name">Your name:</label>
  151. <input type="text" name="dev_name" id="dev_name" placeholder="">
  152. </p>
  153. <p class="grid">
  154. <label for="client_name">Your client's name:</label>
  155. <input type="text" name="client_name" id="client_name" placeholder="">
  156. </p>
  157. <small>
  158. Names appear above signatures when&nbsp;set.
  159. </small>
  160. </form>
  161. </details>
  162. <!-- Email fields -->
  163. <details class="animate slide delay-0">
  164. <summary>
  165. Email addresses
  166. </summary>
  167. <form class="panel flexi">
  168. <p class="grid">
  169. <label for="dev_email">Your email:</label>
  170. <input type="email" name="dev_email" id="dev_email" placeholder="you@example.com">
  171. </p>
  172. <p class="grid">
  173. <label for="client_email">Your client's email:</label>
  174. <input type="email" name="client_email" id="client_email" placeholder="client@example.com">
  175. </p>
  176. <small>
  177. Optional. If set, the contract will send a confirmation email to both
  178. addresses when the second
  179. party signs the contract.
  180. </small>
  181. </form>
  182. </details>
  183. <!-- Shortcodes -->
  184. <details class="animate slide delay-0">
  185. <summary>
  186. Shortcodes
  187. </summary>
  188. <form class="repeater-form | panel flexi">
  189. <template class="repeater-item-template">
  190. <article class="repeater-item">
  191. <div class="repeater-item-field">
  192. <label class="grid">
  193. <span>Replace this: </span>
  194. <input class="repeater-item-name" type="text" placeholder="[shortcode]">
  195. </label>
  196. </div>
  197. <div class="repeater-item-field">
  198. <label class="grid">
  199. <span>With this: </span>
  200. <input class="repeater-item-value" type="text" placeholder="value">
  201. </label>
  202. </div>
  203. <button class="remove-btn close-button secondary danger animate delay-1 roll"
  204. type="button" aria-label="remove item" title="remove">
  205. <span>❌</span>
  206. </button>
  207. <footer class="repeater-info">
  208. <small class="">
  209. Complete both fields above to
  210. <strong style="white-space: nowrap;">add a new shortcode</strong>
  211. </small>
  212. </footer>
  213. </article>
  214. </template>
  215. <output>
  216. </output>
  217. <footer>
  218. <button class="add-btn | button size-300" type="submit">
  219. <span>
  220. + Add another one
  221. </span>
  222. </button>
  223. <button class="save-btn | button size-300 | animate fade" type="button">💾 save</button>
  224. </footer>
  225. <hr style="width: 100%; opacity: .5; margin: 0;">
  226. <details class="flow panel">
  227. <summary style="color: inherit; padding: 0; opacity: .6;">
  228. <small>
  229. What is a shortcode?
  230. </small>
  231. </summary>
  232. <div class="flow">
  233. <p>
  234. Shortcodes are concise snippets,
  235. conventionally enclosed in square brackets, such as <i>[price]</i>.
  236. </p>
  237. <p>
  238. They get automatically replaced
  239. with the actual value, e.g: <i>$1000</i>
  240. when a contract is generated.
  241. </p>
  242. </div>
  243. </details>
  244. </form>
  245. </details>
  246. <!-- Reset data -->
  247. <details class="danger | animate slide delay-0">
  248. <summary>
  249. Reset data
  250. </summary>
  251. <div class="panel" style="display: flex;align-items: center;gap: 1rem;">
  252. <div>
  253. <button id="clear-local-storage" type="button" class="button danger size-300" style="white-space: nowrap;">
  254. <span>Reset <span class="hide-small">data</span></span>
  255. <span class="icon">
  256. <svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 24 24" height="1em"
  257. width="1em" xmlns="http://www.w3.org/2000/svg">
  258. <use href="#icon-delete"></use>
  259. </svg>
  260. </span>
  261. </button>
  262. </div>
  263. <small>
  264. <span>
  265. <b>
  266. Local browser
  267. data will be deleted
  268. </b>
  269. and replaced with default&nbsp;content.
  270. </span>
  271. </small>
  272. </div>
  273. </details>
  274. </div>
  275. <form class="generator-download-options sticky-1 flow | animate slide delay-0" id="download-form" name="download-form">
  276. <h3>Download File</h3>
  277. <!-- Filename field -->
  278. <div class="flexi">
  279. <p class="grid">
  280. <label class="animate slide" for="contract_filename">
  281. <svg aria-label="PHP extension" stroke="currentColor" fill="currentColor" stroke-width="0" role="img"
  282. viewBox="0 0 24 24" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">
  283. <use href="#icon-php"></use>
  284. </svg>
  285. Filename:
  286. </label>
  287. <span class="animate slide delay-1">
  288. <input type="text" name="contract_filename" id="contract_filename" value=""
  289. required>&nbsp;.php
  290. </span>
  291. </p>
  292. </div>
  293. <!-- Download Button -->
  294. <div class="grid">
  295. <button id="download" type="submit"
  296. style="margin-inline-start: 2px; justify-self: start;"
  297. class="button primary size-300 | animate slide delay-4">
  298. <span>Download</span>
  299. <span class="icon">
  300. <svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24"
  301. stroke-linecap="round" stroke-linejoin="round" height="1em" width="1em"
  302. xmlns="http://www.w3.org/2000/svg">
  303. <use href="#icon-download"></use>
  304. </svg>
  305. </span>
  306. </button>
  307. </div>
  308. </form>
  309. <!--
  310. How it works > You upload this file on your own server or domain. You send your client a link to it. They sign. Optionally, you both get an email notification.
  311. -->
  312. <div class="footer flow border-top">
  313. <p style="font-size: 1rem; font-weight: 600; text-wrap: balance;">This template contains general information and should not
  314. be considered legal advice.</p>
  315. <p>View on <a href="https://github.com/nonsalant/contract/">GitHub</a>. Built by <a
  316. href="https://stefanmatei.com">Stefan Matei</a>.</p>
  317. </div>
  318. </div>
  319. </footer>
  320. <!-- svg icon data -->
  321. <svg class="hidden">
  322. <symbol id="down-circle">
  323. <path
  324. d="M690 405h-46.9c-10.2 0-19.9 4.9-25.9 13.2L512 563.6 406.8 418.2c-6-8.3-15.6-13.2-25.9-13.2H334c-6.5 0-10.3 7.4-6.5 12.7l178 246c3.2 4.4 9.7 4.4 12.9 0l178-246c3.9-5.3.1-12.7-6.4-12.7z">
  325. </path>
  326. <path
  327. d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z">
  328. </path>
  329. </symbol>
  330. <symbol id="icon-new-tab">
  331. <path fill="currentColor"
  332. d="M576 24v127.984c0 21.461-25.96 31.98-40.971 16.971l-35.707-35.709-243.523 243.523c-9.373 9.373-24.568 9.373-33.941 0l-22.627-22.627c-9.373-9.373-9.373-24.569 0-33.941L442.756 76.676l-35.703-35.705C391.982 25.9 402.656 0 424.024 0H552c13.255 0 24 10.745 24 24zM407.029 270.794l-16 16A23.999 23.999 0 0 0 384 303.765V448H64V128h264a24.003 24.003 0 0 0 16.97-7.029l16-16C376.089 89.851 365.381 64 344 64H48C21.49 64 0 85.49 0 112v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V287.764c0-21.382-25.852-32.09-40.971-16.97z">
  333. </path>
  334. </symbol>
  335. <symbol id="icon-php">
  336. <path
  337. d="M7.01 10.207h-.944l-.515 2.648h.838c.556 0 .97-.105 1.242-.314.272-.21.455-.559.55-1.049.092-.47.05-.802-.124-.995-.175-.193-.523-.29-1.047-.29zM12 5.688C5.373 5.688 0 8.514 0 12s5.373 6.313 12 6.313S24 15.486 24 12c0-3.486-5.373-6.312-12-6.312zm-3.26 7.451c-.261.25-.575.438-.917.551-.336.108-.765.164-1.285.164H5.357l-.327 1.681H3.652l1.23-6.326h2.65c.797 0 1.378.209 1.744.628.366.418.476 1.002.33 1.752a2.836 2.836 0 0 1-.305.847c-.143.255-.33.49-.561.703zm4.024.715l.543-2.799c.063-.318.039-.536-.068-.651-.107-.116-.336-.174-.687-.174H11.46l-.704 3.625H9.388l1.23-6.327h1.367l-.327 1.682h1.218c.767 0 1.295.134 1.586.401s.378.7.263 1.299l-.572 2.944h-1.389zm7.597-2.265a2.782 2.782 0 0 1-.305.847c-.143.255-.33.49-.561.703a2.44 2.44 0 0 1-.917.551c-.336.108-.765.164-1.286.164h-1.18l-.327 1.682h-1.378l1.23-6.326h2.649c.797 0 1.378.209 1.744.628.366.417.477 1.001.331 1.751zM17.766 10.207h-.943l-.516 2.648h.838c.557 0 .971-.105 1.242-.314.272-.21.455-.559.551-1.049.092-.47.049-.802-.125-.995s-.524-.29-1.047-.29z">
  338. </path>
  339. </symbol>
  340. <symbol id="icon-download">
  341. <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
  342. <polyline points="7 10 12 15 17 10"></polyline>
  343. <line x1="12" y1="15" x2="12" y2="3"></line>
  344. </symbol>
  345. <symbol id="icon-delete">
  346. <path fill="none" d="M0 0h24v24H0z"></path>
  347. <path fill="none" d="M0 0h24v24H0V0z"></path>
  348. <path
  349. d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zm2.46-7.12l1.41-1.41L12 12.59l2.12-2.12 1.41 1.41L13.41 14l2.12 2.12-1.41 1.41L12 15.41l-2.12 2.12-1.41-1.41L10.59 14l-2.13-2.12zM15.5 4l-1-1h-5l-1 1H5v2h14V4z">
  350. </path>
  351. </symbol>
  352. <!-- <symbol id="icon-qr">
  353. <path
  354. d="M5 1h-4v4h4v-4zM6 0v0 6h-6v-6h6zM2 2h2v2h-2zM15 1h-4v4h4v-4zM16 0v0 6h-6v-6h6zM12 2h2v2h-2zM5 11h-4v4h4v-4zM6 10v0 6h-6v-6h6zM2 12h2v2h-2zM7 0h1v1h-1zM8 1h1v1h-1zM7 2h1v1h-1zM8 3h1v1h-1zM7 4h1v1h-1zM8 5h1v1h-1zM7 6h1v1h-1zM7 8h1v1h-1zM8 9h1v1h-1zM7 10h1v1h-1zM8 11h1v1h-1zM7 12h1v1h-1zM8 13h1v1h-1zM7 14h1v1h-1zM8 15h1v1h-1zM15 8h1v1h-1zM1 8h1v1h-1zM2 7h1v1h-1zM0 7h1v1h-1zM4 7h1v1h-1zM5 8h1v1h-1zM6 7h1v1h-1zM9 8h1v1h-1zM10 7h1v1h-1zM11 8h1v1h-1zM12 7h1v1h-1zM13 8h1v1h-1zM14 7h1v1h-1zM15 10h1v1h-1zM9 10h1v1h-1zM10 9h1v1h-1zM11 10h1v1h-1zM13 10h1v1h-1zM14 9h1v1h-1zM15 12h1v1h-1zM9 12h1v1h-1zM10 11h1v1h-1zM12 11h1v1h-1zM13 12h1v1h-1zM14 11h1v1h-1zM15 14h1v1h-1zM10 13h1v1h-1zM11 14h1v1h-1zM12 13h1v1h-1zM13 14h1v1h-1zM10 15h1v1h-1zM12 15h1v1h-1zM14 15h1v1h-1z">
  355. </path>
  356. </symbol> -->
  357. <symbol id="icon-preview">
  358. <path
  359. d="M942.2 486.2C847.4 286.5 704.1 186 512 186c-192.2 0-335.4 100.5-430.2 300.3a60.3 60.3 0 0 0 0 51.5C176.6 737.5 319.9 838 512 838c192.2 0 335.4-100.5 430.2-300.3 7.7-16.2 7.7-35 0-51.5zM512 766c-161.3 0-279.4-81.8-362.7-254C232.6 339.8 350.7 258 512 258c161.3 0 279.4 81.8 362.7 254C791.5 684.2 673.4 766 512 766zm-4-430c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176zm0 288c-61.9 0-112-50.1-112-112s50.1-112 112-112 112 50.1 112 112-50.1 112-112 112z">
  360. </path>
  361. </symbol>
  362. <symbol id="icon-erase">
  363. <path
  364. d="M20.454,19.028h-7.01l6.62-6.63a2.935,2.935,0,0,0,.87-2.09,2.844,2.844,0,0,0-.87-2.05l-3.42-3.44a2.93,2.93,0,0,0-4.13.01L3.934,13.4a2.946,2.946,0,0,0,0,4.14l1.48,1.49H3.554a.5.5,0,0,0,0,1h16.9A.5.5,0,0,0,20.454,19.028Zm-7.24-13.5a1.956,1.956,0,0,1,2.73,0l3.42,3.44a1.868,1.868,0,0,1,.57,1.35,1.93,1.93,0,0,1-.57,1.37l-5.64,5.64-6.15-6.16Zm-1.19,13.5h-5.2l-2.18-2.2a1.931,1.931,0,0,1,0-2.72l2.23-2.23,6.15,6.15Z">
  365. </path>
  366. </symbol>
  367. </svg>
  368. <!-- Preview modal -->
  369. <dialog class="modal" id="modal-preview">
  370. <header class="modal-header">
  371. <button id="close-modal-preview" class="close-button button" aria-label="close" type="button"></button>
  372. </header>
  373. <iframe frameborder="0" id="iframe" title="Preview"></iframe>
  374. </dialog>
  375. <!-- QR modal -->
  376. <!-- <dialog class="modal flow" id="modal-qr">
  377. <div class="qr-code-container">
  378. <button id="close-modal-qr" class="close-button button" aria-label="close" type="button"></button>
  379. <canvas id="generator-qr-code"></canvas>
  380. </div>
  381. </dialog> -->
  382. </body>
  383. </html>