visuddhinanda 2 місяців тому
батько
коміт
a5cb05e9c0
58 змінених файлів з 5822 додано та 0 видалено
  1. 0 0
      api-v12/public/assets/css/ananke/main.min.css
  2. 54 0
      api-v12/public/assets/css/blog/css2
  3. 4 0
      api-v12/public/assets/css/blog/style.min.663803bebe609202d5b39d848f2d7c2dc8b598a2d879efa079fa88893d29c49c.css
  4. BIN
      api-v12/public/assets/gallery/01.jpg
  5. BIN
      api-v12/public/assets/gallery/02.jpg
  6. BIN
      api-v12/public/assets/gallery/03.jpg
  7. BIN
      api-v12/public/assets/gallery/04.jpg
  8. BIN
      api-v12/public/assets/gallery/05.jpg
  9. BIN
      api-v12/public/assets/images/avatar/ai-assistant.png
  10. BIN
      api-v12/public/assets/images/avatar/claude-color.png
  11. BIN
      api-v12/public/assets/images/avatar/deepseek-color.png
  12. BIN
      api-v12/public/assets/images/avatar/doubao-color.png
  13. BIN
      api-v12/public/assets/images/avatar/gemini-color.png
  14. BIN
      api-v12/public/assets/images/avatar/grok.png
  15. BIN
      api-v12/public/assets/images/avatar/kimi-color.png
  16. BIN
      api-v12/public/assets/images/avatar/openai.png
  17. BIN
      api-v12/public/assets/images/avatar/qwen-color.png
  18. BIN
      api-v12/public/assets/images/cover/1/214.jpg
  19. BIN
      api-v12/public/assets/images/cover/zh-hans/1/156.png
  20. BIN
      api-v12/public/assets/images/cover/zh-hans/1/276.png
  21. BIN
      api-v12/public/assets/images/cover/zh-hans/1/277.png
  22. BIN
      api-v12/public/assets/images/cover/zh-hans/1/279.png
  23. BIN
      api-v12/public/assets/images/favicon.ico
  24. BIN
      api-v12/public/assets/images/hero-1.jpg
  25. BIN
      api-v12/public/assets/images/hero-2.jpg
  26. BIN
      api-v12/public/assets/images/hero.jpg
  27. BIN
      api-v12/public/assets/images/logo_mps.png
  28. BIN
      api-v12/public/assets/images/wikipali_logo.png
  29. 89 0
      api-v12/public/assets/images/wikipali_logo.svg
  30. 0 0
      api-v12/public/assets/js/blog/main.1e9a3bafd846ced4c345d084b355fb8c7bae75701c338f8a1f8a82c780137826.js
  31. 0 0
      api-v12/public/assets/js/blog/vibrant.min.js
  32. BIN
      api-v12/public/assets/solarize/81022c3314ffc605ad71a490c5d5ad15eb59ece2-person.png
  33. 39 0
      api-v12/public/assets/solarize/animate.css
  34. 314 0
      api-v12/public/assets/solarize/debugbar.css
  35. 1216 0
      api-v12/public/assets/solarize/debugbar.js
  36. 70 0
      api-v12/public/assets/solarize/init.js
  37. 1 0
      api-v12/public/assets/solarize/jquery-3.x.min.js
  38. 1 0
      api-v12/public/assets/solarize/jquery.dropotron.min.js
  39. 1 0
      api-v12/public/assets/solarize/jquery.min.js
  40. 32 0
      api-v12/public/assets/solarize/notices.css
  41. 33 0
      api-v12/public/assets/solarize/openhandler.css
  42. 202 0
      api-v12/public/assets/solarize/openhandler.js
  43. 1 0
      api-v12/public/assets/solarize/plausible.outbound-links.js
  44. 64 0
      api-v12/public/assets/solarize/sash-ribbon.css
  45. 2 0
      api-v12/public/assets/solarize/saved_resource.html
  46. 1 0
      api-v12/public/assets/solarize/skel-layers.min.js
  47. 1 0
      api-v12/public/assets/solarize/skel.min.js
  48. 12 0
      api-v12/public/assets/solarize/style-wide.css
  49. 811 0
      api-v12/public/assets/solarize/style.css
  50. 261 0
      api-v12/public/assets/solarize/widgets.css
  51. 589 0
      api-v12/public/assets/solarize/widgets.js
  52. 0 0
      api-v12/public/assets/typhoon/css/form-styles.css
  53. 0 0
      api-v12/public/assets/typhoon/css/glightbox.min.css
  54. 1 0
      api-v12/public/assets/typhoon/css/notices.css
  55. 0 0
      api-v12/public/assets/typhoon/css/site.css
  56. 1956 0
      api-v12/public/assets/typhoon/js/alpine.js
  57. 67 0
      api-v12/public/assets/typhoon/js/appearance.js
  58. 0 0
      api-v12/public/assets/typhoon/js/glightbox.min.js

Різницю між файлами не показано, бо вона завелика
+ 0 - 0
api-v12/public/assets/css/ananke/main.min.css


+ 54 - 0
api-v12/public/assets/css/blog/css2

@@ -0,0 +1,54 @@
+/* latin-ext */
+@font-face {
+  font-family: 'Lato';
+  font-style: normal;
+  font-weight: 300;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/lato/v24/S6u9w4BMUTPHh7USSwaPGR_p.woff2) format('woff2');
+  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Lato';
+  font-style: normal;
+  font-weight: 300;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/lato/v24/S6u9w4BMUTPHh7USSwiPGQ.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Lato';
+  font-style: normal;
+  font-weight: 400;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/lato/v24/S6uyw4BMUTPHjxAwXjeu.woff2) format('woff2');
+  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Lato';
+  font-style: normal;
+  font-weight: 400;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/lato/v24/S6uyw4BMUTPHjx4wXg.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}
+/* latin-ext */
+@font-face {
+  font-family: 'Lato';
+  font-style: normal;
+  font-weight: 700;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/lato/v24/S6u9w4BMUTPHh6UVSwaPGR_p.woff2) format('woff2');
+  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
+}
+/* latin */
+@font-face {
+  font-family: 'Lato';
+  font-style: normal;
+  font-weight: 700;
+  font-display: swap;
+  src: url(https://fonts.gstatic.com/s/lato/v24/S6u9w4BMUTPHh6UVSwiPGQ.woff2) format('woff2');
+  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+}

Різницю між файлами не показано, бо вона завелика
+ 4 - 0
api-v12/public/assets/css/blog/style.min.663803bebe609202d5b39d848f2d7c2dc8b598a2d879efa079fa88893d29c49c.css


BIN
api-v12/public/assets/gallery/01.jpg


BIN
api-v12/public/assets/gallery/02.jpg


BIN
api-v12/public/assets/gallery/03.jpg


BIN
api-v12/public/assets/gallery/04.jpg


BIN
api-v12/public/assets/gallery/05.jpg


BIN
api-v12/public/assets/images/avatar/ai-assistant.png


BIN
api-v12/public/assets/images/avatar/claude-color.png


BIN
api-v12/public/assets/images/avatar/deepseek-color.png


BIN
api-v12/public/assets/images/avatar/doubao-color.png


BIN
api-v12/public/assets/images/avatar/gemini-color.png


BIN
api-v12/public/assets/images/avatar/grok.png


BIN
api-v12/public/assets/images/avatar/kimi-color.png


BIN
api-v12/public/assets/images/avatar/openai.png


BIN
api-v12/public/assets/images/avatar/qwen-color.png


BIN
api-v12/public/assets/images/cover/1/214.jpg


BIN
api-v12/public/assets/images/cover/zh-hans/1/156.png


BIN
api-v12/public/assets/images/cover/zh-hans/1/276.png


BIN
api-v12/public/assets/images/cover/zh-hans/1/277.png


BIN
api-v12/public/assets/images/cover/zh-hans/1/279.png


BIN
api-v12/public/assets/images/favicon.ico


BIN
api-v12/public/assets/images/hero-1.jpg


BIN
api-v12/public/assets/images/hero-2.jpg


BIN
api-v12/public/assets/images/hero.jpg


BIN
api-v12/public/assets/images/logo_mps.png


BIN
api-v12/public/assets/images/wikipali_logo.png


+ 89 - 0
api-v12/public/assets/images/wikipali_logo.svg

@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 24.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.0" id="wikipali_logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
+	 y="0px" viewBox="0 0 100 50" style="enable-background:new 0 0 100 50;" xml:space="preserve">
+<g id="圖層_1">
+	<g id="Group_12" transform="translate(-396 -320)">
+		<g id="Group_2" transform="translate(396 320)">
+			<g id="Group_1" transform="translate(39.472 12.369)">
+				<g id="Path_1">
+					<path style="fill:#FFFFFF;" d="M-5.9,19.5c-0.2,0-0.3-0.1-0.5-0.2c-0.1-0.1-0.2-0.2-0.3-0.4l-2.2-8.2v-0.1c0-0.1,0-0.2,0.1-0.3
+						c0.1-0.1,0.2-0.2,0.3-0.2h0.8c0.2,0,0.3,0.1,0.5,0.2c0.1,0.1,0.2,0.2,0.3,0.4l1.1,4.5c0,0,0.2,0.9,0.5,2.6l0,0l0,0l0,0l0,0
+						c0.4-1.7,0.6-2.6,0.6-2.6l1.2-4.5c0.1-0.3,0.4-0.6,0.7-0.6h0.6c0.3,0,0.6,0.2,0.7,0.6l1.2,4.5c0.1,0.3,0.2,0.7,0.3,1.3
+						c0.1,0.6,0.2,1,0.3,1.3l0,0l0,0c0,0,0,0,0.1,0c0-0.2,0.1-0.6,0.2-1.2c0.3-0.6,0.4-1,0.5-1.4l1.1-4.5c0.1-0.3,0.4-0.6,0.7-0.6
+						h0.7c0.1,0,0.3,0.1,0.3,0.2c0,0.1,0.1,0.2,0.1,0.3v0.1l-2.1,8.2c0,0.2-0.1,0.3-0.3,0.4c-0.1,0.1-0.3,0.2-0.5,0.2H0
+						c-0.2,0-0.3-0.1-0.5-0.2c-0.1-0.1-0.2-0.2-0.3-0.4l-1-4.1c-0.1-0.4-0.3-1.3-0.6-2.7c0,0,0,0-0.1,0c0,0,0,0-0.1,0
+						c-0.2,1.2-0.4,2.1-0.6,2.7l-1,4.1c0,0.2-0.1,0.3-0.3,0.4c-0.1,0.1-0.3,0.2-0.5,0.2H-5.9L-5.9,19.5z"/>
+				</g>
+				<g id="Path_2">
+					<path style="fill:#FFFFFF;" d="M8.1,8.1C7.8,8.3,7.5,8.4,7.2,8.4S6.6,8.3,6.3,8.1C6.1,7.9,5.9,7.6,5.9,7.3S6,6.7,6.2,6.5
+						c0.2-0.2,0.6-0.3,0.9-0.3c0.3,0,0.7,0.1,0.9,0.3C8.2,6.7,8.4,7,8.4,7.3C8.4,7.6,8.3,7.9,8.1,8.1z M6.8,19.5
+						c-0.3,0-0.6-0.3-0.6-0.6l0,0v-8.2c0-0.2,0.1-0.3,0.2-0.4c0.1-0.1,0.3-0.2,0.4-0.2h0.7c0.2,0,0.3,0.1,0.4,0.2
+						c0.1,0.1,0.2,0.3,0.2,0.4v8.2c0,0.3-0.3,0.6-0.6,0.6l0,0H6.8z"/>
+				</g>
+				<g id="Path_3">
+					<path style="fill:#FFFFFF;" d="M11.8,19.5c-0.3,0-0.6-0.3-0.6-0.6l0,0V6.5c0-0.2,0.1-0.3,0.2-0.4c0.1-0.1,0.3-0.2,0.4-0.2h0.7
+						c0.2,0,0.3,0.1,0.4,0.2c0.1,0.1,0.2,0.3,0.2,0.4v8.1l0,0l0,0l3.3-4.1c0.2-0.3,0.6-0.5,1-0.4h1c0.1,0,0.2,0.1,0.2,0.2
+						c0.1,0.1,0,0.2,0,0.3l-2.8,3.3V14l3.2,5c0,0,0,0.1,0.1,0.2c0,0.1,0,0.1-0.1,0.2s-0.2,0.2-0.3,0.2h-0.9c-0.4,0-0.7-0.2-0.9-0.5
+						l-2.2-3.7c0,0,0,0-0.1,0l-1.5,1.7c0,0,0,0.1-0.1,0.1v1.7c0,0.3-0.3,0.6-0.6,0.6l0,0L11.8,19.5z"/>
+				</g>
+				<g id="Path_4">
+					<path style="fill:#FFFFFF;" d="M23,8.1c-0.2,0.2-0.6,0.3-0.9,0.3s-0.6-0.1-0.9-0.3c-0.2-0.2-0.3-0.5-0.3-0.8s0.1-0.6,0.3-0.8
+						c0.2-0.2,0.6-0.3,0.9-0.3s0.7,0.1,0.9,0.3c0.2,0.2,0.4,0.5,0.4,0.8C23.4,7.6,23.3,7.9,23,8.1z M21.8,19.5
+						c-0.3,0-0.6-0.3-0.6-0.6l0,0v-8.2c0-0.2,0.1-0.3,0.2-0.4c0.1-0.1,0.3-0.2,0.4-0.2h0.7c0.2,0,0.3,0.1,0.4,0.2
+						c0.1,0.1,0.2,0.3,0.2,0.4v8.2c0,0.3-0.3,0.6-0.6,0.6l0,0H21.8z"/>
+				</g>
+				<g id="Path_5">
+					<path style="fill:#FFFFFF;" d="M26.8,23.3c-0.3,0-0.6-0.3-0.6-0.6l0,0v-12c0-0.3,0.3-0.6,0.6-0.6l0,0h0.4
+						c0.2,0,0.3,0.1,0.4,0.2c0.1,0.1,0.2,0.3,0.2,0.4v0.4l0,0l0,0c0.8-0.7,1.8-1.2,2.9-1.2c1.1,0,2.1,0.4,2.7,1.3c0.7,1,1,2.2,1,3.5
+						c0,0.7-0.1,1.4-0.3,2.1c-0.2,0.6-0.5,1.1-0.9,1.6c-0.4,0.4-0.8,0.7-1.3,1c-0.5,0.2-1,0.3-1.5,0.3c-0.9,0-1.8-0.4-2.4-1l0,0l0,0
+						l0,0v1.5v2.4c0,0.3-0.3,0.6-0.6,0.6l0,0L26.8,23.3L26.8,23.3z M30.2,18.2c0.7,0,1.3-0.3,1.7-0.9c0.5-0.7,0.7-1.6,0.7-2.5
+						c0-2.1-0.7-3.2-2.2-3.2c-0.8,0.1-1.6,0.5-2.2,1.1l-0.1,0.1v4.4c0,0,0,0.1,0.1,0.1C28.8,17.8,29.5,18.1,30.2,18.2L30.2,18.2z"/>
+				</g>
+				<g id="Path_6">
+					<path style="fill:#FFFFFF;" d="M39.1,19.7c-0.7,0-1.4-0.2-2-0.7c-1.1-1.1-1-2.8,0.1-3.9c0.1-0.1,0.3-0.3,0.5-0.4
+						c1.3-0.7,2.7-1.1,4.2-1.2c0,0,0.1,0,0.1-0.1c0-1.3-0.6-2-1.8-2c-0.8,0-1.5,0.2-2.2,0.6c-0.1,0.1-0.3,0.1-0.4,0.1
+						c-0.2,0-0.3-0.1-0.3-0.3L37,11.6c-0.1-0.1-0.1-0.3-0.1-0.5s0.1-0.3,0.3-0.4c1-0.6,2.1-0.9,3.3-0.9c1-0.1,1.9,0.3,2.6,1
+						c0.6,0.9,0.9,1.9,0.8,2.9v5c0,0.3-0.3,0.6-0.6,0.6l0,0h-0.4c-0.2,0-0.3-0.1-0.4-0.2c-0.1-0.1-0.2-0.3-0.2-0.4l-0.1-0.5l0,0l0,0
+						C41.3,19.2,40.2,19.7,39.1,19.7z M38.5,8.1c-0.3,0-0.6-0.3-0.6-0.6l0,0V7.3c0-0.3,0.3-0.6,0.6-0.6l0,0h4.1
+						c0.3,0,0.6,0.3,0.6,0.6l0,0v0.1c0,0.3-0.3,0.6-0.6,0.6l0,0h-4.1V8.1z M39.7,18.2c0.8-0.1,1.6-0.4,2.2-1c0,0,0.1-0.1,0-0.1V15
+						c0-0.1,0-0.1-0.1-0.1c-1,0.1-1.9,0.3-2.8,0.8c-0.5,0.3-0.8,0.8-0.8,1.3c0,0.4,0.1,0.7,0.4,1C38.9,18.1,39.3,18.2,39.7,18.2
+						L39.7,18.2z"/>
+				</g>
+				<g id="Path_7">
+					<path style="fill:#FFFFFF;" d="M48.8,19.7c-0.6,0.1-1.1-0.2-1.5-0.6c-0.3-0.5-0.5-1.2-0.5-1.8V6.5c0-0.2,0.1-0.3,0.2-0.4
+						c0.1-0.1,0.3-0.2,0.4-0.2h0.7c0.2,0,0.3,0.1,0.4,0.2c0.1,0.1,0.2,0.3,0.2,0.4v10.9c0,0.3,0.1,0.5,0.3,0.7c0,0,0.1,0,0.1,0.1
+						c0.1,0,0.1,0.1,0.2,0.1l0.1,0.1l0.1,0.1v0.1l0.1,0.4v0.1c0,0.1,0,0.2-0.1,0.3c-0.1,0.1-0.2,0.2-0.4,0.2
+						C49.1,19.7,48.9,19.7,48.8,19.7z"/>
+				</g>
+				<g id="Path_8">
+					<path style="fill:#FFFFFF;" d="M53.9,8.1c-0.2,0.2-0.6,0.3-0.9,0.3c-0.3,0-0.6-0.1-0.9-0.3c-0.2-0.2-0.4-0.5-0.3-0.8
+						c0-0.3,0.1-0.6,0.3-0.8c0.2-0.2,0.6-0.3,0.9-0.3c0.3,0,0.7,0.1,0.9,0.3c0.2,0.2,0.4,0.5,0.4,0.8C54.3,7.6,54.2,7.9,53.9,8.1z
+						 M52.7,19.5c-0.3,0-0.6-0.3-0.6-0.6l0,0v-8.2c0-0.2,0.1-0.3,0.2-0.4c0.1-0.1,0.3-0.2,0.4-0.2h0.7c0.2,0,0.3,0.1,0.4,0.2
+						c0.1,0.1,0.2,0.3,0.2,0.4v8.2c0,0.3-0.3,0.6-0.6,0.6l0,0H52.7z"/>
+				</g>
+			</g>
+			<g id="Path_9">
+				<path style="fill:#F1CA23;" d="M18.9,34.4c-0.5,0-1-0.4-1-1l0,0v-3.6c0-5.6,2.7-8.8,7.3-8.8c0.5,0,1,0.4,1,1c0,0.5-0.4,1-1,1
+					l0,0c-3.5,0-5.3,2.3-5.3,6.8v3.6C19.8,34,19.4,34.4,18.9,34.4L18.9,34.4z"/>
+			</g>
+			<g id="Path_10">
+				<path style="fill:#F1CA23;" d="M20.8,45.5c-0.5,0-1-0.4-1-1c0-0.5,0.4-1,1-1l0,0c1.9,0,3.3-2.6,3.3-6.3V26.6c0-0.5,0.4-1,1-1
+					c0.5,0,1,0.4,1,1v10.6C26.1,42.9,23.4,45.5,20.8,45.5z"/>
+			</g>
+			<g id="Path_11">
+				<path style="fill:#F1CA23;" d="M14.6,34.4c-0.5,0-1-0.4-1-1l0,0V11.3c0-0.5,0.4-1,1-1c0.5,0,1,0.4,1,1v22.1
+					C15.6,34,15.1,34.4,14.6,34.4L14.6,34.4z"/>
+			</g>
+			<g id="Path_12">
+				<path style="fill:#F1CA23;" d="M10.3,34.4c-0.5,0-1-0.4-1-1l0,0V11.3c0-0.5,0.4-1,1-1c0.5,0,1,0.4,1,1v22.1
+					C11.3,34,10.9,34.4,10.3,34.4L10.3,34.4z"/>
+			</g>
+			<g id="Path_13">
+				<path style="fill:#F1CA23;" d="M6.1,34.4c-0.5,0-1-0.4-1-1l0,0V11.3c0-0.5,0.4-1,1-1s1,0.4,1,1v22.1C7.1,34,6.6,34.4,6.1,34.4z"
+					/>
+			</g>
+		</g>
+	</g>
+</g>
+</svg>

Різницю між файлами не показано, бо вона завелика
+ 0 - 0
api-v12/public/assets/js/blog/main.1e9a3bafd846ced4c345d084b355fb8c7bae75701c338f8a1f8a82c780137826.js


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
api-v12/public/assets/js/blog/vibrant.min.js


BIN
api-v12/public/assets/solarize/81022c3314ffc605ad71a490c5d5ad15eb59ece2-person.png


+ 39 - 0
api-v12/public/assets/solarize/animate.css

@@ -0,0 +1,39 @@
+#github-corner:hover .octo-arm {
+	animation: octocat-wave 560ms ease-in-out;
+}
+
+@keyframes octocat-wave {
+	0% {
+		transform: rotate(0deg);
+	}
+
+	20% {
+		transform: rotate(-25deg);
+	}
+
+	40% {
+		transform: rotate(10deg);
+	}
+
+	60% {
+		transform: rotate(-25deg);
+	}
+
+	80% {
+		transform: rotate(10deg);
+	}
+
+	100% {
+		transform: rotate(0deg);
+	}
+}
+
+@media (max-width: 500px) {
+	#github-corner:hover .octo-arm {
+		animation: none;
+	}
+
+	#github-corner .octo-arm {
+		animation: octocat-wave 560ms ease-in-out;
+	}
+}

+ 314 - 0
api-v12/public/assets/solarize/debugbar.css

@@ -0,0 +1,314 @@
+/* Hide debugbar when printing a page */
+@media print {
+  div.phpdebugbar {
+    display: none;
+  }
+}
+
+div.phpdebugbar {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  border-top: 0;
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
+  background: #fff;
+  z-index: 10000;
+  font-size: 14px;
+  color: #000;
+  text-align: left;
+  line-height: 1;
+  letter-spacing: normal;
+  direction: ltr;
+}
+
+div.phpdebugbar a,
+div.phpdebugbar-openhandler {
+  cursor: pointer;
+}
+
+div.phpdebugbar-drag-capture {
+  position: fixed;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  z-index: 10001;
+  background: none;
+  display: none;
+  cursor: ns-resize;
+}
+
+div.phpdebugbar-closed {
+    width: auto;
+}
+
+div.phpdebugbar * {
+  margin: 0;
+  padding: 0;
+  border: 0;
+  font-weight: normal;
+  text-decoration: none;
+  clear: initial;
+  width: auto;
+  -moz-box-sizing: content-box;
+       box-sizing: content-box;
+}
+
+div.phpdebugbar ol, div.phpdebugbar ul {
+  list-style: none;
+}
+
+div.phpdebugbar table {
+  border-collapse: collapse;
+  border-spacing: 0;
+}
+
+div.phpdebugbar input[type='text'], div.phpdebugbar input[type='password'] {
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
+  background: #fff;
+  font-size: 14px;
+  color: #000;
+  border: 0;
+  padding: 0;
+  margin: 0;
+}
+
+div.phpdebugbar code, div.phpdebugbar pre, div.phpdebugbar samp {
+  background: none;
+  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
+  font-size: 1em;
+  border: 0;
+  padding: 0;
+  margin: 0;
+}
+
+div.phpdebugbar code, div.phpdebugbar pre {
+  color: #000;
+}
+
+div.phpdebugbar pre.sf-dump {
+  color: #a0a000;
+  outline: 0;
+}
+
+a.phpdebugbar-restore-btn {
+  float: left;
+  padding: 5px 8px;
+  font-size: 14px;
+  color: #555;
+  text-decoration: none;
+  border-right: 1px solid #ddd;
+}
+
+div.phpdebugbar-resize-handle {
+  display: none;
+  height: 4px;
+  margin-top: -4px;
+  width: 100%;
+  background: none;
+  border-bottom: 1px solid #ccc;
+  cursor: ns-resize;
+}
+
+div.phpdebugbar-closed, div.phpdebugbar-minimized{
+  border-top: 1px solid #ccc;
+}
+/* -------------------------------------- */
+
+div.phpdebugbar-header, a.phpdebugbar-restore-btn {
+    background: #efefef url(data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2020%2020%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Ccircle%20fill%3D%22%23000%22%20cx%3D%2210%22%20cy%3D%2210%22%20r%3D%229%22%2F%3E%3Cpath%20d%3D%22M6.039%208.342c.463%200%20.772.084.927.251.154.168.191.455.11.862-.084.424-.247.727-.487.908-.241.182-.608.272-1.1.272h-.743l.456-2.293h.837zm-2.975%204.615h1.22l.29-1.457H5.62c.461%200%20.84-.047%201.139-.142.298-.095.569-.254.812-.477.205-.184.37-.387.497-.608.127-.222.217-.466.27-.734.13-.65.032-1.155-.292-1.518-.324-.362-.84-.543-1.545-.543H4.153l-1.089%205.479zM9.235%206.02h1.21l-.289%201.458h1.079c.679%200%201.147.115%201.405.347.258.231.335.607.232%201.125l-.507%202.55h-1.23l.481-2.424c.055-.276.035-.464-.06-.565-.095-.1-.298-.15-.608-.15H9.98L9.356%2011.5h-1.21l1.089-5.48M15.566%208.342c.464%200%20.773.084.928.251.154.168.19.455.11.862-.084.424-.247.727-.488.908-.24.182-.607.272-1.1.272h-.742l.456-2.293h.836zm-2.974%204.615h1.22l.29-1.457h1.046c.461%200%20.84-.047%201.139-.142.298-.095.569-.254.812-.477.205-.184.37-.387.497-.608.127-.222.217-.466.27-.734.129-.65.032-1.155-.292-1.518-.324-.362-.84-.543-1.545-.543H13.68l-1.089%205.479z%22%20fill%3D%22%23FFF%22%2F%3E%3C%2Fsvg%3E)  no-repeat 5px 4px / 20px 20px;
+}
+div.phpdebugbar-header {
+  padding-left: 29px;
+  min-height: 26px;
+  line-height: 16px;
+}
+div.phpdebugbar-header:before, div.phpdebugbar-header:after {
+  display: table;
+  line-height: 0;
+  content: "";
+}
+div.phpdebugbar-header:after {
+  clear: both;
+}
+div.phpdebugbar-header-left {
+  float: left;
+}
+div.phpdebugbar-header-right {
+  float: right;
+}
+div.phpdebugbar-header > div > * {
+  padding: 5px 5px;
+  font-size: 14px;
+  color: #555;
+  text-decoration: none;
+}
+div.phpdebugbar-header-left > * {
+  float: left;
+}
+div.phpdebugbar-header-right > * {
+  float: right;
+}
+div.phpdebugbar-header-right > select {
+  padding: 0;
+}
+
+/* -------------------------------------- */
+
+span.phpdebugbar-indicator,
+a.phpdebugbar-indicator,
+a.phpdebugbar-close-btn {
+  border-right: 1px solid #ddd;
+}
+
+a.phpdebugbar-tab.phpdebugbar-active {
+  background: #ccc;
+  color: #444;
+  background-image: linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%);
+  background-image: -o-linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%);
+  background-image: -moz-linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%);
+  background-image: -webkit-linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%);
+  background-image: -ms-linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%);
+  background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0.41, rgb(173,173,173)), color-stop(0.71, rgb(209,209,209)));
+}
+  a.phpdebugbar-tab span.phpdebugbar-badge {
+    display: none;
+    margin-left: 5px;
+    font-size: 11px;
+    line-height: 14px;
+    padding: 0 6px;
+    background: #ccc;
+    border-radius: 4px;
+    color: #555;
+    font-weight: normal;
+    text-shadow: none;
+    vertical-align: middle;
+  }
+  a.phpdebugbar-tab i {
+    display: none;
+    vertical-align: middle;
+  }
+  a.phpdebugbar-tab span.phpdebugbar-badge.phpdebugbar-visible {
+    display: inline;
+  }
+  a.phpdebugbar-tab span.phpdebugbar-badge.phpdebugbar-important {
+    background: #ed6868;
+    color: white;
+  }
+
+a.phpdebugbar-close-btn, a.phpdebugbar-open-btn, a.phpdebugbar-restore-btn, a.phpdebugbar-minimize-btn , a.phpdebugbar-maximize-btn {
+  width: 16px;
+  height: 16px;
+}
+
+a.phpdebugbar-minimize-btn , a.phpdebugbar-maximize-btn {
+  padding-right: 0 !important;
+}
+
+a.phpdebugbar-maximize-btn { display: none}
+
+a.phpdebugbar-minimize-btn { display: block}
+
+div.phpdebugbar-minimized a.phpdebugbar-maximize-btn { display: block}
+
+div.phpdebugbar-minimized a.phpdebugbar-minimize-btn { display: none}
+
+a.phpdebugbar-minimize-btn {
+  background:url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201792%201792%22%20id%3D%22chevron-down%22%3E%3Cpath%20d%3D%22M1683%20808l-742%20741q-19%2019-45%2019t-45-19l-742-741q-19-19-19-45.5t19-45.5l166-165q19-19%2045-19t45%2019l531%20531%20531-531q19-19%2045-19t45%2019l166%20165q19%2019%2019%2045.5t-19%2045.5z%22%2F%3E%3C%2Fsvg%3E) no-repeat 6px 6px / 14px 14px;
+}
+
+a.phpdebugbar-maximize-btn {
+  background:url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201792%201792%22%20id%3D%22chevron-up%22%3E%3Cpath%20d%3D%22M1683%201331l-166%20165q-19%2019-45%2019t-45-19l-531-531-531%20531q-19%2019-45%2019t-45-19l-166-165q-19-19-19-45.5t19-45.5l742-741q19-19%2045-19t45%2019l742%20741q19%2019%2019%2045.5t-19%2045.5z%22%2F%3E%3C%2Fsvg%3E) no-repeat 6px 6px / 14px 14px;
+}
+
+a.phpdebugbar-close-btn {
+  background: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201792%201792%22%20id%3D%22close%22%3E%3Cpath%20d%3D%22M1490%201322q0%2040-28%2068l-136%20136q-28%2028-68%2028t-68-28l-294-294-294%20294q-28%2028-68%2028t-68-28l-136-136q-28-28-28-68t28-68l294-294-294-294q-28-28-28-68t28-68l136-136q28-28%2068-28t68%2028l294%20294%20294-294q28-28%2068-28t68%2028l136%20136q28%2028%2028%2068t-28%2068l-294%20294%20294%20294q28%2028%2028%2068z%22%2F%3E%3C%2Fsvg%3E) no-repeat 9px 6px / 14px 14px;
+}
+
+a.phpdebugbar-open-btn {
+  background: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201792%201792%22%20id%3D%22folder-open%22%3E%3Cpath%20d%3D%22M1815%20952q0%2031-31%2066l-336%20396q-43%2051-120.5%2086.5t-143.5%2035.5h-1088q-34%200-60.5-13t-26.5-43q0-31%2031-66l336-396q43-51%20120.5-86.5t143.5-35.5h1088q34%200%2060.5%2013t26.5%2043zm-343-344v160h-832q-94%200-197%2047.5t-164%20119.5l-337%20396-5%206q0-4-.5-12.5t-.5-12.5v-960q0-92%2066-158t158-66h320q92%200%20158%2066t66%20158v32h544q92%200%20158%2066t66%20158z%22%2F%3E%3C%2Fsvg%3E) no-repeat 8px 6px / 14px 14px;
+}
+
+.phpdebugbar-indicator {
+  position: relative;
+  cursor: pointer;
+}
+  .phpdebugbar-indicator span.phpdebugbar-text {
+    margin-left: 5px;
+  }
+  .phpdebugbar-indicator span.phpdebugbar-tooltip {
+    display: none;
+    position: absolute;
+    top: -30px;
+    background: #efefef;
+    opacity: .7;
+    border: 1px solid #ccc;
+    color: #555;
+    font-size: 11px;
+    padding: 2px 3px;
+    z-index: 1000;
+    text-align: center;
+    width: 200%;
+    right: 0;
+  }
+  .phpdebugbar-indicator:hover span.phpdebugbar-tooltip:not(.phpdebugbar-disabled) {
+    display: block;
+  }
+
+select.phpdebugbar-datasets-switcher {
+  float: right;
+  display: none;
+  margin: 2px 0 0 7px;
+  max-width: 200px;
+  max-height: 23px;
+  padding: 0;
+}
+
+/* -------------------------------------- */
+
+div.phpdebugbar-body {
+  border-top: 1px solid #ccc;
+  display: none;
+  position: relative;
+  height: 300px;
+}
+
+/* -------------------------------------- */
+
+div.phpdebugbar-panel {
+  display: none;
+  height: 100%;
+  overflow: auto;
+  width: 100%;
+}
+div.phpdebugbar-panel.phpdebugbar-active {
+  display: block;
+}
+
+/* -------------------------------------- */
+
+div.phpdebugbar-mini-design a.phpdebugbar-tab {
+  position: relative;
+  border-right: 1px solid #ddd;
+}
+  div.phpdebugbar-mini-design a.phpdebugbar-tab span.phpdebugbar-text {
+    display: none;
+  }
+  div.phpdebugbar-mini-design a.phpdebugbar-tab:hover span.phpdebugbar-text {
+    display: block;
+    position: absolute;
+    top: -30px;
+    background: #efefef;
+    opacity: .7;
+    border: 1px solid #ccc;
+    color: #555;
+    font-size: 11px;
+    padding: 2px 3px;
+    z-index: 1000;
+    text-align: center;
+    right: 0;
+  }
+  div.phpdebugbar-mini-design a.phpdebugbar-tab i {
+    display:inline-block;
+  }

+ 1216 - 0
api-v12/public/assets/solarize/debugbar.js

@@ -0,0 +1,1216 @@
+if (typeof(PhpDebugBar) == 'undefined') {
+    // namespace
+    var PhpDebugBar = {};
+    PhpDebugBar.$ = jQuery;
+}
+
+(function($) {
+
+    if (typeof(localStorage) == 'undefined') {
+        // provide mock localStorage object for dumb browsers
+        localStorage = {
+            setItem: function(key, value) {},
+            getItem: function(key) { return null; }
+        };
+    }
+
+    if (typeof(PhpDebugBar.utils) == 'undefined') {
+        PhpDebugBar.utils = {};
+    }
+
+    /**
+     * Returns the value from an object property.
+     * Using dots in the key, it is possible to retrieve nested property values
+     *
+     * @param {Object} dict
+     * @param {String} key
+     * @param {Object} default_value
+     * @return {Object}
+     */
+    var getDictValue = PhpDebugBar.utils.getDictValue = function(dict, key, default_value) {
+        var d = dict, parts = key.split('.');
+        for (var i = 0; i < parts.length; i++) {
+            if (!d[parts[i]]) {
+                return default_value;
+            }
+            d = d[parts[i]];
+        }
+        return d;
+    }
+
+    /**
+     * Counts the number of properties in an object
+     *
+     * @param {Object} obj
+     * @return {Integer}
+     */
+    var getObjectSize = PhpDebugBar.utils.getObjectSize = function(obj) {
+        if (Object.keys) {
+            return Object.keys(obj).length;
+        }
+        var count = 0;
+        for (var k in obj) {
+            if (obj.hasOwnProperty(k)) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    /**
+     * Returns a prefixed css class name
+     *
+     * @param {String} cls
+     * @return {String}
+     */
+    PhpDebugBar.utils.csscls = function(cls, prefix) {
+        if (cls.indexOf(' ') > -1) {
+            var clss = cls.split(' '), out = [];
+            for (var i = 0, c = clss.length; i < c; i++) {
+                out.push(PhpDebugBar.utils.csscls(clss[i], prefix));
+            }
+            return out.join(' ');
+        }
+        if (cls.indexOf('.') === 0) {
+            return '.' + prefix + cls.substr(1);
+        }
+        return prefix + cls;
+    };
+
+    /**
+     * Creates a partial function of csscls where the second
+     * argument is already defined
+     *
+     * @param  {string} prefix
+     * @return {Function}
+     */
+    PhpDebugBar.utils.makecsscls = function(prefix) {
+        var f = function(cls) {
+            return PhpDebugBar.utils.csscls(cls, prefix);
+        };
+        return f;
+    }
+
+    var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-');
+
+
+    // ------------------------------------------------------------------
+
+    /**
+     * Base class for all elements with a visual component
+     *
+     * @param {Object} options
+     * @constructor
+     */
+    var Widget = PhpDebugBar.Widget = function(options) {
+        this._attributes = $.extend({}, this.defaults);
+        this._boundAttributes = {};
+        this.$el = $('<' + this.tagName + ' />');
+        if (this.className) {
+            this.$el.addClass(this.className);
+        }
+        this.initialize.apply(this, [options || {}]);
+        this.render.apply(this);
+    };
+
+    $.extend(Widget.prototype, {
+
+        tagName: 'div',
+
+        className: null,
+
+        defaults: {},
+
+        /**
+         * Called after the constructor
+         *
+         * @param {Object} options
+         */
+        initialize: function(options) {
+            this.set(options);
+        },
+
+        /**
+         * Called after the constructor to render the element
+         */
+        render: function() {},
+
+        /**
+         * Sets the value of an attribute
+         *
+         * @param {String} attr Can also be an object to set multiple attributes at once
+         * @param {Object} value
+         */
+        set: function(attr, value) {
+            if (typeof(attr) != 'string') {
+                for (var k in attr) {
+                    this.set(k, attr[k]);
+                }
+                return;
+            }
+
+            this._attributes[attr] = value;
+            if (typeof(this._boundAttributes[attr]) !== 'undefined') {
+                for (var i = 0, c = this._boundAttributes[attr].length; i < c; i++) {
+                    this._boundAttributes[attr][i].apply(this, [value]);
+                }
+            }
+        },
+
+        /**
+         * Checks if an attribute exists and is not null
+         *
+         * @param {String} attr
+         * @return {[type]} [description]
+         */
+        has: function(attr) {
+            return typeof(this._attributes[attr]) !== 'undefined' && this._attributes[attr] !== null;
+        },
+
+        /**
+         * Returns the value of an attribute
+         *
+         * @param {String} attr
+         * @return {Object}
+         */
+        get: function(attr) {
+            return this._attributes[attr];
+        },
+
+        /**
+         * Registers a callback function that will be called whenever the value of the attribute changes
+         *
+         * If cb is a jQuery element, text() will be used to fill the element
+         *
+         * @param {String} attr
+         * @param {Function} cb
+         */
+        bindAttr: function(attr, cb) {
+            if ($.isArray(attr)) {
+                for (var i = 0, c = attr.length; i < c; i++) {
+                    this.bindAttr(attr[i], cb);
+                }
+                return;
+            }
+
+            if (typeof(this._boundAttributes[attr]) == 'undefined') {
+                this._boundAttributes[attr] = [];
+            }
+            if (typeof(cb) == 'object') {
+                var el = cb;
+                cb = function(value) { el.text(value || ''); };
+            }
+            this._boundAttributes[attr].push(cb);
+            if (this.has(attr)) {
+                cb.apply(this, [this._attributes[attr]]);
+            }
+        }
+
+    });
+
+
+    /**
+     * Creates a subclass
+     *
+     * Code from Backbone.js
+     *
+     * @param {Array} props Prototype properties
+     * @return {Function}
+     */
+    Widget.extend = function(props) {
+        var parent = this;
+
+        var child = function() { return parent.apply(this, arguments); };
+        $.extend(child, parent);
+
+        var Surrogate = function() { this.constructor = child; };
+        Surrogate.prototype = parent.prototype;
+        child.prototype = new Surrogate;
+        $.extend(child.prototype, props);
+
+        child.__super__ = parent.prototype;
+
+        return child;
+    };
+
+    // ------------------------------------------------------------------
+
+    /**
+     * Tab
+     *
+     * A tab is composed of a tab label which is always visible and
+     * a tab panel which is visible only when the tab is active.
+     *
+     * The panel must contain a widget. A widget is an object which has
+     * an element property containing something appendable to a jQuery object.
+     *
+     * Options:
+     *  - title
+     *  - badge
+     *  - widget
+     *  - data: forward data to widget data
+     */
+    var Tab = Widget.extend({
+
+        className: csscls('panel'),
+
+        render: function() {
+            this.$tab = $('<a />').addClass(csscls('tab'));
+
+            this.$icon = $('<i />').appendTo(this.$tab);
+            this.bindAttr('icon', function(icon) {
+                if (icon) {
+                    this.$icon.attr('class', 'phpdebugbar-fa phpdebugbar-fa-' + icon);
+                } else {
+                    this.$icon.attr('class', '');
+                }
+            });
+
+            this.bindAttr('title', $('<span />').addClass(csscls('text')).appendTo(this.$tab));
+
+            this.$badge = $('<span />').addClass(csscls('badge')).appendTo(this.$tab);
+            this.bindAttr('badge', function(value) {
+                if (value !== null) {
+                    this.$badge.text(value);
+                    this.$badge.addClass(csscls('visible'));
+                } else {
+                    this.$badge.removeClass(csscls('visible'));
+                }
+            });
+
+            this.bindAttr('widget', function(widget) {
+                this.$el.empty().append(widget.$el);
+            });
+
+            this.bindAttr('data', function(data) {
+                if (this.has('widget')) {
+                    this.get('widget').set('data', data);
+                }
+            })
+        }
+
+    });
+
+    // ------------------------------------------------------------------
+
+    /**
+     * Indicator
+     *
+     * An indicator is a text and an icon to display single value information
+     * right inside the always visible part of the debug bar
+     *
+     * Options:
+     *  - icon
+     *  - title
+     *  - tooltip
+     *  - data: alias of title
+     */
+    var Indicator = Widget.extend({
+
+        tagName: 'span',
+
+        className: csscls('indicator'),
+
+        render: function() {
+            this.$icon = $('<i />').appendTo(this.$el);
+            this.bindAttr('icon', function(icon) {
+                if (icon) {
+                    this.$icon.attr('class', 'phpdebugbar-fa phpdebugbar-fa-' + icon);
+                } else {
+                    this.$icon.attr('class', '');
+                }
+            });
+
+            this.bindAttr(['title', 'data'], $('<span />').addClass(csscls('text')).appendTo(this.$el));
+
+            this.$tooltip = $('<span />').addClass(csscls('tooltip disabled')).appendTo(this.$el);
+            this.bindAttr('tooltip', function(tooltip) {
+                if (tooltip) {
+                    this.$tooltip.text(tooltip).removeClass(csscls('disabled'));
+                } else {
+                    this.$tooltip.addClass(csscls('disabled'));
+                }
+            });
+        }
+
+    });
+
+    // ------------------------------------------------------------------
+
+    /**
+     * Dataset title formater
+     *
+     * Formats the title of a dataset for the select box
+     */
+    var DatasetTitleFormater = PhpDebugBar.DatasetTitleFormater = function(debugbar) {
+        this.debugbar = debugbar;
+    };
+
+    $.extend(DatasetTitleFormater.prototype, {
+
+        /**
+         * Formats the title of a dataset
+         *
+         * @this {DatasetTitleFormater}
+         * @param {String} id
+         * @param {Object} data
+         * @param {String} suffix
+         * @return {String}
+         */
+        format: function(id, data, suffix) {
+            if (suffix) {
+                suffix = ' ' + suffix;
+            } else {
+                suffix = '';
+            }
+
+            var nb = getObjectSize(this.debugbar.datasets) + 1;
+
+            if (typeof(data['__meta']) === 'undefined') {
+                return "#" + nb + suffix;
+            }
+
+            var uri = data['__meta']['uri'], filename;
+            if (uri.length && uri.charAt(uri.length - 1) === '/') {
+                // URI ends in a trailing /: get the portion before then to avoid returning an empty string
+                filename = uri.substr(0, uri.length - 1); // strip trailing '/'
+                filename = filename.substr(filename.lastIndexOf('/') + 1); // get last path segment
+                filename += '/'; // add the trailing '/' back
+            } else {
+                filename = uri.substr(uri.lastIndexOf('/') + 1);
+            }
+
+            // truncate the filename in the label, if it's too long
+            var maxLength = 150;
+            if (filename.length > maxLength) {
+                filename = filename.substr(0, maxLength) + '...';
+            }
+
+            var label = "#" + nb + " " + filename + suffix + ' (' + data['__meta']['datetime'].split(' ')[1] + ')';
+            return label;
+        }
+
+    });
+
+    // ------------------------------------------------------------------
+
+
+    /**
+     * DebugBar
+     *
+     * Creates a bar that appends itself to the body of your page
+     * and sticks to the bottom.
+     *
+     * The bar can be customized by adding tabs and indicators.
+     * A data map is used to fill those controls with data provided
+     * from datasets.
+     */
+    var DebugBar = PhpDebugBar.DebugBar = Widget.extend({
+
+        className: "phpdebugbar " + csscls('minimized'),
+
+        options: {
+            bodyMarginBottom: true,
+            bodyMarginBottomHeight: 0
+        },
+
+        initialize: function() {
+            this.controls = {};
+            this.dataMap = {};
+            this.datasets = {};
+            this.firstTabName = null;
+            this.activePanelName = null;
+            this.datesetTitleFormater = new DatasetTitleFormater(this);
+            this.options.bodyMarginBottomHeight = parseInt($('body').css('margin-bottom'));
+            this.registerResizeHandler();
+        },
+
+        /**
+         * Register resize event, for resize debugbar with reponsive css.
+         *
+         * @this {DebugBar}
+         */
+        registerResizeHandler: function() {
+            if (typeof this.resize.bind == 'undefined') return;
+
+            var f = this.resize.bind(this);
+            this.respCSSSize = 0;
+            $(window).resize(f);
+            setTimeout(f, 20);
+        },
+
+        /**
+         * Resizes the debugbar to fit the current browser window
+         */
+        resize: function() {
+            var contentSize = this.respCSSSize;
+            if (this.respCSSSize == 0) {
+                this.$header.find("> div > *:visible").each(function () {
+                    contentSize += $(this).outerWidth();
+                });
+            }
+
+            var currentSize = this.$header.width();
+            var cssClass = "phpdebugbar-mini-design";
+            var bool = this.$header.hasClass(cssClass);
+
+            if (currentSize <= contentSize && !bool) {
+                this.respCSSSize = contentSize;
+                this.$header.addClass(cssClass);
+            } else if (contentSize < currentSize && bool) {
+                this.respCSSSize = 0;
+                this.$header.removeClass(cssClass);
+            }
+
+            // Reset height to ensure bar is still visible
+            this.setHeight(this.$body.height());
+        },
+
+        /**
+         * Initialiazes the UI
+         *
+         * @this {DebugBar}
+         */
+        render: function() {
+            var self = this;
+            this.$el.appendTo('body');
+            this.$dragCapture = $('<div />').addClass(csscls('drag-capture')).appendTo(this.$el);
+            this.$resizehdle = $('<div />').addClass(csscls('resize-handle')).appendTo(this.$el);
+            this.$header = $('<div />').addClass(csscls('header')).appendTo(this.$el);
+            this.$headerLeft = $('<div />').addClass(csscls('header-left')).appendTo(this.$header);
+            this.$headerRight = $('<div />').addClass(csscls('header-right')).appendTo(this.$header);
+            var $body = this.$body = $('<div />').addClass(csscls('body')).appendTo(this.$el);
+            this.recomputeBottomOffset();
+
+            // dragging of resize handle
+            var pos_y, orig_h;
+            this.$resizehdle.on('mousedown', function(e) {
+                orig_h = $body.height(), pos_y = e.pageY;
+                $body.parents().on('mousemove', mousemove).on('mouseup', mouseup);
+                self.$dragCapture.show();
+                e.preventDefault();
+            });
+            var mousemove = function(e) {
+                var h = orig_h + (pos_y - e.pageY);
+                self.setHeight(h);
+            };
+            var mouseup = function() {
+                $body.parents().off('mousemove', mousemove).off('mouseup', mouseup);
+                self.$dragCapture.hide();
+            };
+
+            // close button
+            this.$closebtn = $('<a />').addClass(csscls('close-btn')).appendTo(this.$headerRight);
+            this.$closebtn.click(function() {
+                self.close();
+            });
+
+            // minimize button
+            this.$minimizebtn = $('<a />').addClass(csscls('minimize-btn') ).appendTo(this.$headerRight);
+            this.$minimizebtn.click(function() {
+                self.minimize();
+            });
+
+            // maximize button
+            this.$maximizebtn = $('<a />').addClass(csscls('maximize-btn') ).appendTo(this.$headerRight);
+            this.$maximizebtn.click(function() {
+                self.restore();
+            });
+
+            // restore button
+            this.$restorebtn = $('<a />').addClass(csscls('restore-btn')).hide().appendTo(this.$el);
+            this.$restorebtn.click(function() {
+                self.restore();
+            });
+
+            // open button
+            this.$openbtn = $('<a />').addClass(csscls('open-btn')).appendTo(this.$headerRight).hide();
+            this.$openbtn.click(function() {
+                self.openHandler.show(function(id, dataset) {
+                    self.addDataSet(dataset, id, "(opened)");
+                    self.showTab();
+                });
+            });
+
+            // select box for data sets
+            this.$datasets = $('<select />').addClass(csscls('datasets-switcher')).appendTo(this.$headerRight);
+            this.$datasets.change(function() {
+                self.dataChangeHandler(self.datasets[this.value]);
+                self.showTab();
+            });
+        },
+
+        /**
+         * Sets the height of the debugbar body section
+         * Forces the height to lie within a reasonable range
+         * Stores the height in local storage so it can be restored
+         * Resets the document body bottom offset
+         *
+         * @this {DebugBar}
+         */
+        setHeight: function(height) {
+          var min_h = 40;
+          var max_h = $(window).innerHeight() - this.$header.height() - 10;
+          height = Math.min(height, max_h);
+          height = Math.max(height, min_h);
+          this.$body.css('height', height);
+          localStorage.setItem('phpdebugbar-height', height);
+          this.recomputeBottomOffset();
+        },
+
+        /**
+         * Restores the state of the DebugBar using localStorage
+         * This is not called by default in the constructor and
+         * needs to be called by subclasses in their init() method
+         *
+         * @this {DebugBar}
+         */
+        restoreState: function() {
+            // bar height
+            var height = localStorage.getItem('phpdebugbar-height');
+            this.setHeight(height || this.$body.height());
+
+            // bar visibility
+            var open = localStorage.getItem('phpdebugbar-open');
+            if (open && open == '0') {
+                this.close();
+            } else {
+                var visible = localStorage.getItem('phpdebugbar-visible');
+                if (visible && visible == '1') {
+                    var tab = localStorage.getItem('phpdebugbar-tab');
+                    if (this.isTab(tab)) {
+                        this.showTab(tab);
+                    }
+                }
+            }
+        },
+
+        /**
+         * Creates and adds a new tab
+         *
+         * @this {DebugBar}
+         * @param {String} name Internal name
+         * @param {Object} widget A widget object with an element property
+         * @param {String} title The text in the tab, if not specified, name will be used
+         * @return {Tab}
+         */
+        createTab: function(name, widget, title) {
+            var tab = new Tab({
+                title: title || (name.replace(/[_\-]/g, ' ').charAt(0).toUpperCase() + name.slice(1)),
+                widget: widget
+            });
+            return this.addTab(name, tab);
+        },
+
+        /**
+         * Adds a new tab
+         *
+         * @this {DebugBar}
+         * @param {String} name Internal name
+         * @param {Tab} tab Tab object
+         * @return {Tab}
+         */
+        addTab: function(name, tab) {
+            if (this.isControl(name)) {
+                throw new Error(name + ' already exists');
+            }
+
+            var self = this;
+            tab.$tab.appendTo(this.$headerLeft).click(function() {
+                if (!self.isMinimized() && self.activePanelName == name) {
+                    self.minimize();
+                } else {
+                    self.showTab(name);
+                }
+            });
+            tab.$el.appendTo(this.$body);
+
+            this.controls[name] = tab;
+            if (this.firstTabName == null) {
+                this.firstTabName = name;
+            }
+            return tab;
+        },
+
+        /**
+         * Creates and adds an indicator
+         *
+         * @this {DebugBar}
+         * @param {String} name Internal name
+         * @param {String} icon
+         * @param {String} tooltip
+         * @param {String} position "right" or "left", default is "right"
+         * @return {Indicator}
+         */
+        createIndicator: function(name, icon, tooltip, position) {
+            var indicator = new Indicator({
+                icon: icon,
+                tooltip: tooltip
+            });
+            return this.addIndicator(name, indicator, position);
+        },
+
+        /**
+         * Adds an indicator
+         *
+         * @this {DebugBar}
+         * @param {String} name Internal name
+         * @param {Indicator} indicator Indicator object
+         * @return {Indicator}
+         */
+        addIndicator: function(name, indicator, position) {
+            if (this.isControl(name)) {
+                throw new Error(name + ' already exists');
+            }
+
+            if (position == 'left') {
+                indicator.$el.insertBefore(this.$headerLeft.children().first());
+            } else {
+                indicator.$el.appendTo(this.$headerRight);
+            }
+
+            this.controls[name] = indicator;
+            return indicator;
+        },
+
+        /**
+         * Returns a control
+         *
+         * @param {String} name
+         * @return {Object}
+         */
+        getControl: function(name) {
+            if (this.isControl(name)) {
+                return this.controls[name];
+            }
+        },
+
+        /**
+         * Checks if there's a control under the specified name
+         *
+         * @this {DebugBar}
+         * @param {String} name
+         * @return {Boolean}
+         */
+        isControl: function(name) {
+            return typeof(this.controls[name]) != 'undefined';
+        },
+
+        /**
+         * Checks if a tab with the specified name exists
+         *
+         * @this {DebugBar}
+         * @param {String} name
+         * @return {Boolean}
+         */
+        isTab: function(name) {
+            return this.isControl(name) && this.controls[name] instanceof Tab;
+        },
+
+        /**
+         * Checks if an indicator with the specified name exists
+         *
+         * @this {DebugBar}
+         * @param {String} name
+         * @return {Boolean}
+         */
+        isIndicator: function(name) {
+            return this.isControl(name) && this.controls[name] instanceof Indicator;
+        },
+
+        /**
+         * Removes all tabs and indicators from the debug bar and hides it
+         *
+         * @this {DebugBar}
+         */
+        reset: function() {
+            this.minimize();
+            var self = this;
+            $.each(this.controls, function(name, control) {
+                if (self.isTab(name)) {
+                    control.$tab.remove();
+                }
+                control.$el.remove();
+            });
+            this.controls = {};
+        },
+
+        /**
+         * Open the debug bar and display the specified tab
+         *
+         * @this {DebugBar}
+         * @param {String} name If not specified, display the first tab
+         */
+        showTab: function(name) {
+            if (!name) {
+                if (this.activePanelName) {
+                    name = this.activePanelName;
+                } else {
+                    name = this.firstTabName;
+                }
+            }
+
+            if (!this.isTab(name)) {
+                throw new Error("Unknown tab '" + name + "'");
+            }
+
+            this.$resizehdle.show();
+            this.$body.show();
+            this.recomputeBottomOffset();
+
+            $(this.$header).find('> div > .' + csscls('active')).removeClass(csscls('active'));
+            $(this.$body).find('> .' + csscls('active')).removeClass(csscls('active'));
+
+            this.controls[name].$tab.addClass(csscls('active'));
+            this.controls[name].$el.addClass(csscls('active'));
+            this.activePanelName = name;
+
+            this.$el.removeClass(csscls('minimized'));
+            localStorage.setItem('phpdebugbar-visible', '1');
+            localStorage.setItem('phpdebugbar-tab', name);
+            this.resize();
+        },
+
+        /**
+         * Hide panels and minimize the debug bar
+         *
+         * @this {DebugBar}
+         */
+        minimize: function() {
+            this.$header.find('> div > .' + csscls('active')).removeClass(csscls('active'));
+            this.$body.hide();
+            this.$resizehdle.hide();
+            this.recomputeBottomOffset();
+            localStorage.setItem('phpdebugbar-visible', '0');
+            this.$el.addClass(csscls('minimized'));
+            this.resize();
+        },
+
+        /**
+         * Checks if the panel is minimized
+         *
+         * @return {Boolean}
+         */
+        isMinimized: function() {
+            return this.$el.hasClass(csscls('minimized'));
+        },
+
+        /**
+         * Close the debug bar
+         *
+         * @this {DebugBar}
+         */
+        close: function() {
+            this.$resizehdle.hide();
+            this.$header.hide();
+            this.$body.hide();
+            this.$restorebtn.show();
+            localStorage.setItem('phpdebugbar-open', '0');
+            this.$el.addClass(csscls('closed'));
+            this.recomputeBottomOffset();
+        },
+
+        /**
+         * Checks if the panel is closed
+         *
+         * @return {Boolean}
+         */
+        isClosed: function() {
+            return this.$el.hasClass(csscls('closed'));
+        },
+
+        /**
+         * Restore the debug bar
+         *
+         * @this {DebugBar}
+         */
+        restore: function() {
+            this.$resizehdle.show();
+            this.$header.show();
+            this.$restorebtn.hide();
+            localStorage.setItem('phpdebugbar-open', '1');
+            var tab = localStorage.getItem('phpdebugbar-tab');
+            if (this.isTab(tab)) {
+                this.showTab(tab);
+            } else {
+                this.showTab();
+            }
+            this.$el.removeClass(csscls('closed'));
+            this.resize();
+        },
+
+        /**
+         * Recomputes the margin-bottom css property of the body so
+         * that the debug bar never hides any content
+         */
+        recomputeBottomOffset: function() {
+            if (this.options.bodyMarginBottom) {
+                if (this.isClosed()) {
+                    return $('body').css('margin-bottom', this.options.bodyMarginBottomHeight || '');
+                }
+
+                var offset = parseInt(this.$el.height()) + (this.options.bodyMarginBottomHeight || 0);
+                $('body').css('margin-bottom', offset);
+            }
+        },
+
+        /**
+         * Sets the data map used by dataChangeHandler to populate
+         * indicators and widgets
+         *
+         * A data map is an object where properties are control names.
+         * The value of each property should be an array where the first
+         * item is the name of a property from the data object (nested properties
+         * can be specified) and the second item the default value.
+         *
+         * Example:
+         *     {"memory": ["memory.peak_usage_str", "0B"]}
+         *
+         * @this {DebugBar}
+         * @param {Object} map
+         */
+        setDataMap: function(map) {
+            this.dataMap = map;
+        },
+
+        /**
+         * Same as setDataMap() but appends to the existing map
+         * rather than replacing it
+         *
+         * @this {DebugBar}
+         * @param {Object} map
+         */
+        addDataMap: function(map) {
+            $.extend(this.dataMap, map);
+        },
+
+        /**
+         * Resets datasets and add one set of data
+         *
+         * For this method to be usefull, you need to specify
+         * a dataMap using setDataMap()
+         *
+         * @this {DebugBar}
+         * @param {Object} data
+         * @return {String} Dataset's id
+         */
+        setData: function(data) {
+            this.datasets = {};
+            return this.addDataSet(data);
+        },
+
+        /**
+         * Adds a dataset
+         *
+         * If more than one dataset are added, the dataset selector
+         * will be displayed.
+         *
+         * For this method to be usefull, you need to specify
+         * a dataMap using setDataMap()
+         *
+         * @this {DebugBar}
+         * @param {Object} data
+         * @param {String} id The name of this set, optional
+         * @param {String} suffix
+         * @param {Bool} show Whether to show the new dataset, optional (default: true)
+         * @return {String} Dataset's id
+         */
+        addDataSet: function(data, id, suffix, show) {
+            var label = this.datesetTitleFormater.format(id, data, suffix);
+            id = id || (getObjectSize(this.datasets) + 1);
+            this.datasets[id] = data;
+
+            this.$datasets.append($('<option value="' + id + '">' + label + '</option>'));
+            if (this.$datasets.children().length > 1) {
+                this.$datasets.show();
+            }
+
+            if (typeof(show) == 'undefined' || show) {
+                this.showDataSet(id);
+            }
+            return id;
+        },
+
+        /**
+         * Loads a dataset using the open handler
+         *
+         * @param {String} id
+         * @param {Bool} show Whether to show the new dataset, optional (default: true)
+         */
+        loadDataSet: function(id, suffix, callback, show) {
+            if (!this.openHandler) {
+                throw new Error('loadDataSet() needs an open handler');
+            }
+            var self = this;
+            this.openHandler.load(id, function(data) {
+                self.addDataSet(data, id, suffix, show);
+                self.resize();
+                callback && callback(data);
+            });
+        },
+
+        /**
+         * Returns the data from a dataset
+         *
+         * @this {DebugBar}
+         * @param {String} id
+         * @return {Object}
+         */
+        getDataSet: function(id) {
+            return this.datasets[id];
+        },
+
+        /**
+         * Switch the currently displayed dataset
+         *
+         * @this {DebugBar}
+         * @param {String} id
+         */
+        showDataSet: function(id) {
+            this.dataChangeHandler(this.datasets[id]);
+            this.$datasets.val(id);
+        },
+
+        /**
+         * Called when the current dataset is modified.
+         *
+         * @this {DebugBar}
+         * @param {Object} data
+         */
+        dataChangeHandler: function(data) {
+            var self = this;
+            $.each(this.dataMap, function(key, def) {
+                var d = getDictValue(data, def[0], def[1]);
+                if (key.indexOf(':') != -1) {
+                    key = key.split(':');
+                    self.getControl(key[0]).set(key[1], d);
+                } else {
+                    self.getControl(key).set('data', d);
+                }
+            });
+        },
+
+        /**
+         * Sets the handler to open past dataset
+         *
+         * @this {DebugBar}
+         * @param {object} handler
+         */
+        setOpenHandler: function(handler) {
+            this.openHandler = handler;
+            if (handler !== null) {
+                this.$openbtn.show();
+            } else {
+                this.$openbtn.hide();
+            }
+        },
+
+        /**
+         * Returns the handler to open past dataset
+         *
+         * @this {DebugBar}
+         * @return {object}
+         */
+        getOpenHandler: function() {
+            return this.openHandler;
+        }
+
+    });
+
+    DebugBar.Tab = Tab;
+    DebugBar.Indicator = Indicator;
+
+    // ------------------------------------------------------------------
+
+    /**
+     * AjaxHandler
+     *
+     * Extract data from headers of an XMLHttpRequest and adds a new dataset
+     *
+     * @param {Bool} autoShow Whether to immediately show new datasets, optional (default: true)
+     */
+    var AjaxHandler = PhpDebugBar.AjaxHandler = function(debugbar, headerName, autoShow) {
+        this.debugbar = debugbar;
+        this.headerName = headerName || 'phpdebugbar';
+        this.autoShow = typeof(autoShow) == 'undefined' ? true : autoShow;
+    };
+
+    $.extend(AjaxHandler.prototype, {
+
+        /**
+         * Handles a Fetch API Response or an XMLHttpRequest
+         *
+         * @this {AjaxHandler}
+         * @param {Response|XMLHttpRequest} response
+         * @return {Bool}
+         */
+        handle: function(response) {
+            // Check if the debugbar header is available
+            if (this.isFetch(response) && !response.headers.has(this.headerName + '-id')) {
+                return true;
+            } else if (this.isXHR(response) && response.getAllResponseHeaders().indexOf(this.headerName) === -1) {
+                return true;
+            }
+            if (!this.loadFromId(response)) {
+                return this.loadFromData(response);
+            }
+            return true;
+        },
+
+        getHeader: function(response, header) {
+            if (this.isFetch(response)) {
+                return response.headers.get(header)
+            }
+
+            return response.getResponseHeader(header)
+        },
+
+        isFetch: function(response) {
+            return Object.prototype.toString.call(response) == '[object Response]'
+        },
+
+        isXHR: function(response) {
+            return Object.prototype.toString.call(response) == '[object XMLHttpRequest]'
+        },
+
+        /**
+         * Checks if the HEADER-id exists and loads the dataset using the open handler
+         *
+         * @param {Response|XMLHttpRequest} response
+         * @return {Bool}
+         */
+        loadFromId: function(response) {
+            var id = this.extractIdFromHeaders(response);
+            if (id && this.debugbar.openHandler) {
+                this.debugbar.loadDataSet(id, "(ajax)", undefined, this.autoShow);
+                return true;
+            }
+            return false;
+        },
+
+        /**
+         * Extracts the id from the HEADER-id
+         *
+         * @param {Response|XMLHttpRequest} response
+         * @return {String}
+         */
+        extractIdFromHeaders: function(response) {
+            return this.getHeader(response, this.headerName + '-id');
+        },
+
+        /**
+         * Checks if the HEADER exists and loads the dataset
+         *
+         * @param {Response|XMLHttpRequest} response
+         * @return {Bool}
+         */
+        loadFromData: function(response) {
+            var raw = this.extractDataFromHeaders(response);
+            if (!raw) {
+                return false;
+            }
+
+            var data = this.parseHeaders(raw);
+            if (data.error) {
+                throw new Error('Error loading debugbar data: ' + data.error);
+            } else if(data.data) {
+                this.debugbar.addDataSet(data.data, data.id, "(ajax)", this.autoShow);
+            }
+            return true;
+        },
+
+        /**
+         * Extract the data as a string from headers of an XMLHttpRequest
+         *
+         * @this {AjaxHandler}
+         * @param {Response|XMLHttpRequest} response
+         * @return {string}
+         */
+        extractDataFromHeaders: function(response) {
+            var data = this.getHeader(response, this.headerName);
+            if (!data) {
+                return;
+            }
+            for (var i = 1;; i++) {
+                var header = this.getHeader(response, this.headerName + '-' + i);
+                if (!header) {
+                    break;
+                }
+                data += header;
+            }
+            return decodeURIComponent(data);
+        },
+
+        /**
+         * Parses the string data into an object
+         *
+         * @this {AjaxHandler}
+         * @param {string} data
+         * @return {string}
+         */
+        parseHeaders: function(data) {
+            return JSON.parse(data);
+        },
+
+        /**
+         * Attaches an event listener to fetch
+         *
+         * @this {AjaxHandler}
+         */
+        bindToFetch: function() {
+            var self = this;
+            var proxied = window.fetch;
+
+            if (proxied !== undefined && proxied.polyfill !== undefined) {
+                return;
+            }
+
+            window.fetch = function () {
+                var promise = proxied.apply(this, arguments);
+
+                promise.then(function (response) {
+                    self.handle(response);
+                });
+
+                return promise;
+            };
+        },
+
+        /**
+         * Attaches an event listener to jQuery.ajaxComplete()
+         *
+         * @this {AjaxHandler}
+         * @param {jQuery} jq Optional
+         */
+        bindToJquery: function(jq) {
+            var self = this;
+            jq(document).ajaxComplete(function(e, xhr, settings) {
+                if (!settings.ignoreDebugBarAjaxHandler) {
+                    self.handle(xhr);
+                }
+            });
+        },
+
+        /**
+         * Attaches an event listener to XMLHttpRequest
+         *
+         * @this {AjaxHandler}
+         */
+        bindToXHR: function() {
+            var self = this;
+            var proxied = XMLHttpRequest.prototype.open;
+            XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
+                var xhr = this;
+                this.addEventListener("readystatechange", function() {
+                    var skipUrl = self.debugbar.openHandler ? self.debugbar.openHandler.get('url') : null;
+                    if (xhr.readyState == 4 && url.indexOf(skipUrl) !== 0) {
+                        self.handle(xhr);
+                    }
+                }, false);
+                proxied.apply(this, Array.prototype.slice.call(arguments));
+            };
+        }
+
+    });
+
+})(PhpDebugBar.$);

Різницю між файлами не показано, бо вона завелика
+ 70 - 0
api-v12/public/assets/solarize/init.js


Різницю між файлами не показано, бо вона завелика
+ 1 - 0
api-v12/public/assets/solarize/jquery-3.x.min.js


Різницю між файлами не показано, бо вона завелика
+ 1 - 0
api-v12/public/assets/solarize/jquery.dropotron.min.js


Різницю між файлами не показано, бо вона завелика
+ 1 - 0
api-v12/public/assets/solarize/jquery.min.js


+ 32 - 0
api-v12/public/assets/solarize/notices.css

@@ -0,0 +1,32 @@
+.notices {
+    padding: 1px 1px 1px 30px;
+    margin: 15px 0;
+}
+
+.notices p {
+
+}
+
+.notices.yellow {
+    border-left: 10px solid #f0ad4e;
+    background: #fcf8f2;
+    color: #df8a13;
+}
+
+.notices.red {
+    border-left: 10px solid #d9534f;
+    background: #fdf7f7;
+    color: #b52b27;
+}
+
+.notices.blue {
+    border-left: 10px solid #5bc0de;
+    background: #f4f8fa;
+    color: #28a1c5;
+}
+
+.notices.green {
+    border-left: 10px solid #5cb85c;
+    background: #f1f9f1;
+    color: #3d8b3d;
+}

Різницю між файлами не показано, бо вона завелика
+ 33 - 0
api-v12/public/assets/solarize/openhandler.css


+ 202 - 0
api-v12/public/assets/solarize/openhandler.js

@@ -0,0 +1,202 @@
+if (typeof(PhpDebugBar) == 'undefined') {
+    // namespace
+    var PhpDebugBar = {};
+    PhpDebugBar.$ = jQuery;
+}
+
+(function($) {
+
+    var csscls = function(cls) {
+        return PhpDebugBar.utils.csscls(cls, 'phpdebugbar-openhandler-');
+    };
+
+    PhpDebugBar.OpenHandler = PhpDebugBar.Widget.extend({
+
+        className: 'phpdebugbar-openhandler',
+
+        defaults: {
+            items_per_page: 20
+        },
+
+        render: function() {
+            var self = this;
+
+            this.$el.appendTo('body').hide();
+            this.$closebtn = $('<a><i class="phpdebugbar-fa phpdebugbar-fa-times"></i></a>');
+            this.$table = $('<tbody />');
+            $('<div>PHP DebugBar | Open</div>').addClass(csscls('header')).append(this.$closebtn).appendTo(this.$el);
+            $('<table><thead><tr><th width="150">Date</th><th width="55">Method</th><th>URL</th><th width="125">IP</th><th width="100">Filter data</th></tr></thead></table>').append(this.$table).appendTo(this.$el);
+            this.$actions = $('<div />').addClass(csscls('actions')).appendTo(this.$el);
+
+            this.$closebtn.on('click', function() {
+                self.hide();
+            });
+
+            this.$loadmorebtn = $('<a>Load more</a>')
+                .appendTo(this.$actions)
+                .on('click', function() {
+                    self.find(self.last_find_request, self.last_find_request.offset + self.get('items_per_page'), self.handleFind.bind(self));
+                });
+
+            this.$showonlycurrentbtn = $('<a>Show only current URL</a>')
+                .appendTo(this.$actions)
+                .on('click', function() {
+                    self.$table.empty();
+                    self.find({uri: window.location.pathname}, 0, self.handleFind.bind(self));
+                });
+
+            this.$showallbtn = $('<a>Show all</a>')
+                .appendTo(this.$actions)
+                .on('click', function() {
+                    self.refresh();
+                });
+
+            this.$clearbtn = $('<a>Delete all</a>')
+                .appendTo(this.$actions)
+                .on('click', function() {
+                    self.clear(function() {
+                        self.hide();
+                    });
+                });
+                
+            this.addSearch();
+
+            this.$overlay = $('<div />').addClass(csscls('overlay')).hide().appendTo('body');
+            this.$overlay.on('click', function() {
+                self.hide();
+            });
+        },
+
+        refresh: function() {
+            this.$table.empty();
+            this.$loadmorebtn.show();
+            this.find({}, 0, this.handleFind.bind(this));
+        },
+        
+        addSearch: function(){
+            var self = this;
+            var searchBtn = $('<button />')
+                .text('Search')
+                .attr('type', 'submit')
+                .on('click', function(e) {
+                    self.$table.empty();
+                    var search = {};
+                    var a = $(this).parent().serializeArray();
+                    $.each(a, function() {
+                        if(this.value){
+                            search[this.name] = this.value;
+                        }
+                    });
+
+                    self.find(search, 0, self.handleFind.bind(self));
+                    e.preventDefault();
+                });
+
+            $('<form />')
+                .append('<br/><b>Filter results</b><br/>')
+                .append('Method: <select name="method"><option></option><option>GET</option><option>POST</option><option>PUT</option><option>DELETE</option></select><br/>')
+                .append('Uri: <input type="text" name="uri"><br/>')
+                .append('IP: <input type="text" name="ip"><br/>')
+                .append(searchBtn)
+                .appendTo(this.$actions);
+        },
+
+        handleFind: function(data) {
+            var self = this;
+            $.each(data, function(i, meta) {
+               var a = $('<a />')
+                    .text('Load dataset')
+                    .on('click', function(e) {
+                       self.hide();
+                       self.load(meta['id'], function(data) {
+                           self.callback(meta['id'], data);
+                       });
+                       e.preventDefault();
+                    });
+                    
+                var method = $('<a />')
+                    .text(meta['method'])
+                    .on('click', function(e) {
+                        self.$table.empty();
+                        self.find({method: meta['method']}, 0, self.handleFind.bind(self));
+                        e.preventDefault();
+                    });
+
+                var uri = $('<a />')
+                    .text(meta['uri'])
+                    .on('click', function(e) {
+                        self.hide();
+                        self.load(meta['id'], function(data) {
+                            self.callback(meta['id'], data);
+                        });
+                        e.preventDefault();
+                    });
+
+                var ip = $('<a />')
+                    .text(meta['ip'])
+                    .on('click', function(e) {
+                        self.$table.empty();
+                        self.find({ip: meta['ip']}, 0, self.handleFind.bind(self));
+                        e.preventDefault();
+                    });
+
+                var search = $('<a />')
+                    .text('Show URL')
+                    .on('click', function(e) {
+                        self.$table.empty();
+                        self.find({uri: meta['uri']}, 0, self.handleFind.bind(self));
+                        e.preventDefault();
+                    });
+                    
+                $('<tr />')
+                    .append('<td>' + meta['datetime'] + '</td>')
+                    .append('<td>' + meta['method'] + '</td>')
+                    .append($('<td />').append(uri))
+                    .append($('<td />').append(ip))
+                    .append($('<td />').append(search))
+                    .appendTo(self.$table);
+            });
+            if (data.length < this.get('items_per_page')) {
+                this.$loadmorebtn.hide();
+            }
+        },
+
+        show: function(callback) {
+            this.callback = callback;
+            this.$el.show();
+            this.$overlay.show();
+            this.refresh();
+        },
+
+        hide: function() {
+            this.$el.hide();
+            this.$overlay.hide();
+        },
+
+        find: function(filters, offset, callback) {
+            var data = $.extend({}, filters, {max: this.get('items_per_page'), offset: offset || 0});
+            this.last_find_request = data;
+            this.ajax(data, callback);
+        },
+
+        load: function(id, callback) {
+            this.ajax({op: "get", id: id}, callback);
+        },
+
+        clear: function(callback) {
+            this.ajax({op: "clear"}, callback);
+        },
+
+        ajax: function(data, callback) {
+            $.ajax({
+                dataType: 'json',
+                url: this.get('url'),
+                data: data,
+                success: callback,
+                ignoreDebugBarAjaxHandler: true
+            });
+        }
+
+    });
+
+})(PhpDebugBar.$);

+ 1 - 0
api-v12/public/assets/solarize/plausible.outbound-links.js

@@ -0,0 +1 @@
+!function(){"use strict";var a=window.location,r=window.document,t=window.localStorage,o=r.currentScript,s=o.getAttribute("data-api")||new URL(o.src).origin+"/api/event",l=t&&t.plausible_ignore;function p(t){console.warn("Ignoring Event: "+t)}function e(t,e){if(/^localhost$|^127(\.[0-9]+){0,2}\.[0-9]+$|^\[::1?\]$/.test(a.hostname)||"file:"===a.protocol)return p("localhost");if(!(window._phantom||window.__nightmare||window.navigator.webdriver||window.Cypress)){if("true"==l)return p("localStorage flag");var i={};i.n=t,i.u=a.href,i.d=o.getAttribute("data-domain"),i.r=r.referrer||null,i.w=window.innerWidth,e&&e.meta&&(i.m=JSON.stringify(e.meta)),e&&e.props&&(i.p=JSON.stringify(e.props));var n=new XMLHttpRequest;n.open("POST",s,!0),n.setRequestHeader("Content-Type","text/plain"),n.send(JSON.stringify(i)),n.onreadystatechange=function(){4==n.readyState&&e&&e.callback&&e.callback()}}}function i(t){for(var e=t.target,i="auxclick"==t.type&&2==t.which,n="click"==t.type;e&&(void 0===e.tagName||"a"!=e.tagName.toLowerCase()||!e.href);)e=e.parentNode;e&&e.href&&e.host&&e.host!==a.host&&((i||n)&&plausible("Outbound Link: Click",{props:{url:e.href}}),e.target&&!e.target.match(/^_(self|parent|top)$/i)||t.ctrlKey||t.metaKey||t.shiftKey||!n||(setTimeout(function(){a.href=e.href},150),t.preventDefault()))}r.addEventListener("click",i),r.addEventListener("auxclick",i);var n=window.plausible&&window.plausible.q||[];window.plausible=e;for(var c,d=0;d<n.length;d++)e.apply(this,n[d]);function u(){c!==a.pathname&&(c=a.pathname,e("pageview"))}var w,h=window.history;h.pushState&&(w=h.pushState,h.pushState=function(){w.apply(this,arguments),u()},window.addEventListener("popstate",u)),"prerender"===r.visibilityState?r.addEventListener("visibilitychange",function(){c||"visible"!==r.visibilityState||u()}):u()}();

+ 64 - 0
api-v12/public/assets/solarize/sash-ribbon.css

@@ -0,0 +1,64 @@
+/* thanks to https://codepen.io/nxworld/pen/oLdoWb */
+.sash-box {
+  position: relative;
+  max-width: 225px;
+  /*width: 90%;
+  height: 400px;
+  background: #fff; */
+  box-shadow: 0 0 15px rgba(0,0,0,.1);
+  opacity: 0.85;
+  z-index: 999;
+}
+
+/* common */
+.ribbon {
+  width: 150px;
+  height: 150px;
+  overflow: hidden;
+  position: absolute;
+}
+.ribbon::before,
+.ribbon::after {
+  position: absolute;
+  z-index: -1;
+  content: '';
+  display: block;
+  border: 5px solid #2980b9;
+}
+.ribbon span {
+  position: absolute;
+  display: block;
+  width: 225px;
+  padding: 15px 0;
+  background-color: #3498db;
+  box-shadow: 0 5px 10px rgba(0,0,0,.1);
+  color: #fff;
+  font: 700 18px/1 'Lato', sans-serif;
+  text-shadow: 0 1px 1px rgba(0,0,0,.2);
+  text-transform: uppercase;
+  text-align: center;
+}
+
+/* top left*/
+.ribbon-top-left {
+  top: -10px;
+  left: -10px;
+}
+.ribbon-top-left::before,
+.ribbon-top-left::after {
+  border-top-color: transparent;
+  border-left-color: transparent;
+}
+.ribbon-top-left::before {
+  top: 10px;
+  right: 10px;
+}
+.ribbon-top-left::after {
+  bottom: 10px;
+  left: 10px;
+}
+.ribbon-top-left span {
+  right: -25px;
+  top: 30px;
+  transform: rotate(-45deg);
+}

Різницю між файлами не показано, бо вона завелика
+ 2 - 0
api-v12/public/assets/solarize/saved_resource.html


Різницю між файлами не показано, бо вона завелика
+ 1 - 0
api-v12/public/assets/solarize/skel-layers.min.js


Різницю між файлами не показано, бо вона завелика
+ 1 - 0
api-v12/public/assets/solarize/skel.min.js


+ 12 - 0
api-v12/public/assets/solarize/style-wide.css

@@ -0,0 +1,12 @@
+/*
+	Solarize by TEMPLATED
+	templated.co @templatedco
+	Released for free under the Creative Commons Attribution 3.0 license (templated.co/license)
+*/
+
+/* Basic */
+
+	body, input, select, textarea {
+		font-size: 12pt;
+		line-height: 1.8em;
+	}

+ 811 - 0
api-v12/public/assets/solarize/style.css

@@ -0,0 +1,811 @@
+@import url("font-awesome.min.css");
+@import url("//fonts.googleapis.com/css?family=Open+Sans:300,400,600,700,800");
+
+/*
+	Solarize by TEMPLATED
+	templated.co @templatedco
+	Released for free under the Creative Commons Attribution 3.0 license (templated.co/license)
+*/
+
+/* Basic */
+
+	body {
+		background: #222222;
+	}
+
+		body.loading * {
+			-moz-transition: none !important;
+			-webkit-transition: none !important;
+			-o-transition: none !important;
+			-ms-transition: none !important;
+			transition: none !important;
+			-moz-animation: none !important;
+			-webkit-animation: none !important;
+			-o-animation: none !important;
+			-ms-animation: none !important;
+			animation: none !important;
+		}
+
+	body, input, select, textarea {
+		color: #555555;
+		font-family: 'Open Sans', sans-serif;
+		font-size: 12pt;
+		font-weight: 300;
+		line-height: 1.65em;
+	}
+
+	a {
+		color: #82b440;
+		text-decoration: underline;
+	}
+
+	strong, b {
+		font-weight: 700;
+	}
+
+	em, i {
+		font-style: italic;
+	}
+
+	p, ul, ol, dl, table, blockquote {
+		margin: 0 0 2em 0;
+	}
+
+	p {
+		line-height: 1.8em;
+	}
+
+		p.medium {
+			font-size: 1.4em;
+		}
+
+	h1, h2, h3, h4, h5, h6 {
+		color: inherit;
+		font-weight: 700;
+	}
+
+		h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
+			color: inherit;
+			text-decoration: none;
+		}
+
+	h2 {
+		font-size: 1.5em;
+	}
+
+	h3 {
+		font-size: 1.25em;
+	}
+
+	sub {
+		font-size: 0.8em;
+		position: relative;
+		top: 0.5em;
+	}
+
+	sup {
+		font-size: 0.8em;
+		position: relative;
+		top: -0.5em;
+	}
+
+	hr {
+		border-top: solid 1px #82b440;
+		border: 0;
+		margin-bottom: 1.5em;
+	}
+
+	blockquote {
+		border-left: solid 0.5em #82b440;
+		font-style: italic;
+		padding: 1em 0 1em 2em;
+	}
+
+	section.special, article.special {
+		text-align: center;
+	}
+
+	header.major {
+		padding-bottom: 3em;
+		text-align: center;
+		text-transform: uppercase;
+	}
+
+		header.major h2 {
+			font-size: 2.6em;
+			font-weight: 700;
+		}
+
+		header.major .byline {
+			display: block;
+			padding-top: 1em;
+			letter-spacing: 1px;
+			font-size: 1.4em;
+		}
+
+	footer > :last-child {
+		margin-bottom: 0;
+	}
+
+	footer.major {
+		padding-top: 3em;
+	}
+
+/* Form */
+
+	input[type="text"],
+	input[type="password"],
+	input[type="email"],
+	textarea {
+		-moz-appearance: none;
+		-webkit-appearance: none;
+		-o-appearance: none;
+		-ms-appearance: none;
+		appearance: none;
+		background: none;
+		border: solid 1px #82b440;
+		color: inherit;
+		display: block;
+		outline: 0;
+		padding: 0.75em;
+		text-decoration: none;
+		width: 100%;
+	}
+
+		input[type="text"]:focus,
+		input[type="password"]:focus,
+		input[type="email"]:focus,
+		textarea:focus {
+			border-color: #82b440;
+		}
+
+	input[type="text"],
+	input[type="password"],
+	input[type="email"] {
+		line-height: 1em;
+	}
+
+	::-webkit-input-placeholder {
+		color: inherit;
+		opacity: 0.5;
+		position: relative;
+		top: 3px;
+	}
+
+	:-moz-placeholder {
+		color: inherit;
+		opacity: 0.5;
+	}
+
+	::-moz-placeholder {
+		color: inherit;
+		opacity: 0.5;
+	}
+
+	:-ms-input-placeholder {
+		color: inherit;
+		opacity: 0.5;
+	}
+
+	.formerize-placeholder {
+		color: rgba(85, 85, 85, 0.5) !important;
+	}
+
+/* Image */
+
+	.image {
+		border: 0;
+		position: relative;
+	}
+
+		.image.fit {
+			display: block;
+		}
+
+			.image.fit img {
+				display: block;
+				width: 100%;
+			}
+
+		.image.feature {
+			display: block;
+			margin: 0 0 2em 0;
+		}
+
+			.image.feature img {
+				display: block;
+				width: 100%;
+			}
+
+/* Icon */
+
+	.icon {
+		position: relative;
+	}
+
+		.icon:before {
+			content: "";
+			-moz-osx-font-smoothing: grayscale;
+			-webkit-font-smoothing: antialiased;
+			font-family: FontAwesome;
+			font-style: normal;
+			font-weight: normal;
+			text-transform: none !important;
+		}
+
+		.icon > .label {
+			display: none;
+		}
+
+/* Lists */
+
+	ol.default {
+		list-style: decimal;
+		padding-left: 1.25em;
+	}
+
+		ol.default li {
+			padding-left: 0.25em;
+		}
+
+	ul.default {
+		margin: 0;
+		padding: 0;
+		list-style: none;
+	}
+
+		ul.default li {
+			padding: 0.40em 0em;
+		}
+
+	ul.icons {
+		cursor: default;
+		padding-bottom: 2em;
+	}
+
+		ul.icons li {
+			display: inline-block;
+			line-height: 1em;
+			padding: 0.5em 1em;
+		}
+
+			ul.icons li:first-child {
+				padding-left: 0;
+			}
+
+			ul.icons li span {
+				display: none;
+			}
+
+			ul.icons li a {
+				text-decoration: none;
+				font-size: 2em;
+				color: inherit;
+				opacity: 0.2;
+				-moz-transition: all 0.35s ease-in-out;
+				-webkit-transition: all 0.35s ease-in-out;
+				-o-transition: all 0.35s ease-in-out;
+				-ms-transition: all 0.35s ease-in-out;
+				transition: all 0.35s ease-in-out;
+			}
+
+			ul.icons li a:hover {
+				color: inherit;
+				opacity: 1;
+			}
+
+	ul.actions {
+		cursor: default;
+	}
+
+		ul.actions:last-child {
+			margin-bottom: 0;
+		}
+
+		ul.actions li {
+			display: inline-block;
+			padding: 0 0 0 1.5em;
+		}
+
+			ul.actions li:first-child {
+				padding: 0;
+			}
+
+		ul.actions.vertical li {
+			display: block;
+			padding: 1.5em 0 0 0;
+		}
+
+			ul.actions.vertical li:first-child {
+				padding: 0;
+			}
+
+	ul.special-icons {
+		margin: 0em;
+		padding: 0em;
+	}
+
+		ul.special-icons > li {
+			position: relative;
+			padding: 0.50em 0em 0.50em 0em;
+		}
+
+		ul.special-icons > li:before {
+			position: absolute;
+			left: 0;
+			top: 2em;
+			display: block;
+			background: none;
+			font-size: 2em;
+			border-radius: 5px;
+		}
+
+		ul.special-icons > li:first-child {
+			border-top: none;
+		}
+
+		ul.special-icons h3 {
+			margin-bottom: 0.80em;
+			line-height: 2em;
+			text-transform: uppercase;
+			font-weight: 700;
+			font-size: 1.2em;
+		}
+
+		ul.special-icons span {
+			line-height: 190%;
+		}
+
+		ul.special-icons .fa {
+			float: left;
+			display: inline-block;
+			padding-right: 1em;
+			font-size: 1.4em;
+			color: #82b440;
+		}
+
+		ul.special-icons p {
+			padding-left: 2.7em;
+		}
+
+/* Tables */
+
+	table {
+		width: 100%;
+	}
+
+		table.default {
+			width: 100%;
+		}
+
+			table.default tbody tr {
+				border-bottom: solid 1px #82b440;
+			}
+
+			table.default td {
+				padding: 0.5em 1em 0.5em 1em;
+			}
+
+			table.default th {
+				font-weight: 700;
+				padding: 0.5em 1em 0.5em 1em;
+				text-align: left;
+			}
+
+			table.default thead {
+				background: #555555;
+				color: #fff;
+			}
+
+/* Button */
+
+	input[type="submit"],
+	input[type="reset"],
+	input[type="button"],
+	.button {
+		-moz-appearance: none;
+		-webkit-appearance: none;
+		-o-appearance: none;
+		-ms-appearance: none;
+		appearance: none;
+		background: none;
+		border-radius: none;
+		border: 2px solid;
+		border-color: #82b440;
+		color: #82b440;
+		cursor: pointer;
+		display: inline-block;
+		padding: 0.90em 1.2em;
+		letter-spacing: 1px;
+		text-align: center;
+		text-decoration: none;
+		text-transform: uppercase;
+		font-size: 1.4em;
+		-moz-transition: all 0.35s ease-in-out;
+		-webkit-transition: all 0.35s ease-in-out;
+		-o-transition: all 0.35s ease-in-out;
+		-ms-transition: all 0.35s ease-in-out;
+		transition: all 0.35s ease-in-out;
+	}
+
+		input[type="submit"]:hover,
+		input[type="reset"]:hover,
+		input[type="button"]:hover,
+		.button:hover {
+			background: #82b440;
+			color: white;
+		}
+
+		input[type="submit"].alt,
+		input[type="reset"].alt,
+		input[type="button"].alt,
+		.button.alt {
+			border-color: inherit;
+			color: inherit;
+		}
+
+			input[type="submit"].alt:hover,
+			input[type="reset"].alt:hover,
+			input[type="button"].alt:hover,
+			.button.alt:hover {
+				background: white;
+				color: #82b440;
+			}
+
+		input[type="submit"].fit,
+		input[type="reset"].fit,
+		input[type="button"].fit,
+		.button.fit {
+			width: 100%;
+		}
+
+		input[type="submit"].small,
+		input[type="reset"].small,
+		input[type="button"].small,
+		.button.small {
+			font-size: 0.8em;
+		}
+
+/* Wrapper */
+
+	.wrapper {
+		padding: 6em 0em 4em 0em;
+	}
+
+		.wrapper.style1 {
+			padding: 0em;
+			background: #222222 url('images/banner.jpg') no-repeat;
+			background-size: cover;
+		}
+
+		.wrapper.style2,
+		.wrapper.evenpart {
+			background: #f2f2f2;
+		}
+
+			.wrapper.style2 .major,
+			.wrapper.evenpart .major {
+				text-align: left !important;
+			}
+
+				.wrapper.style2 .major h2,
+				.wrapper.evenpart .major h2 {
+					display: block;
+					margin-bottom: 0.70em;
+					letter-spacing: 1px;
+					line-height: 1.4em;
+					text-transform: uppercase;
+					font-size: 1.8em;
+					font-weight: 400;
+				}
+
+				.wrapper.style2 .major .byline,
+				.wrapper.evenpart .major .byline {
+					letter-spacing: normal;
+					line-height: 1.6em;
+					text-transform: capitalize;
+					font-size: 1.4em;
+				}
+
+			.wrapper.style2 h3,
+			.wrapper.evenpart h3 {
+				display: block;
+				margin-bottom: 1em;
+				letter-spacing: 1px;
+				line-height: 1.4em;
+				text-transform: uppercase;
+				font-size: 1.6em;
+				font-weight: 400;
+			}
+
+		.wrapper.style3,
+		.wrapper.cta {
+			padding-bottom: 6em;
+			background: #82b440;
+			text-align: center;
+			color: white;
+		}
+
+			.wrapper.style3 .container,
+			.wrapper.cta .container {
+				padding-left: 6em;
+				padding-right: 6em;
+			}
+
+			.wrapper.style3 p,
+			.wrapper.cta p {
+				font-size: 1.6em;
+			}
+
+		.wrapper.style4,
+		.wrapper.plain {
+			background: white;
+		}
+
+		.wrapper.style5,
+		.wrapper.portals {
+			background: #82b440;
+			text-align: center;
+			color: white;
+		}
+
+			.wrapper.style5 .image,
+			.wrapper.portals .image {
+				display: block;
+				width: 60%;
+				margin: 0em auto 2em auto;
+			}
+
+				.wrapper.style5 .image img,
+				.wrapper.portals .image img {
+					border-radius: 50%;
+					border: 10px solid;
+					border-color: white;
+				}
+
+/* Header */
+
+	#header {
+		color: white;
+		height: 4em;
+		background: rgba(0, 0, 0, 0.5);
+	}
+
+		#header .container {
+			position: relative;
+		}
+
+	.homepage #logo {
+		display: none;
+	}
+
+	.homepage #nav {
+		position: static;
+		right: none;
+		text-align: center;
+	}
+
+	#logo {
+		line-height: 2em;
+		letter-spacing: 2px;
+		text-transform: uppercase;
+		font-size: 2em;
+		font-weight: 400;
+	}
+
+		#logo h1 {
+			display: inline-block;
+			margin: 0;
+			padding: 0;
+		}
+
+		#logo a {
+			color: inherit;
+		}
+
+	#nav {
+		position: absolute;
+		top: 0;
+		right: 0;
+	}
+
+		#nav > ul {
+			margin: 0;
+		}
+
+			#nav > ul > li {
+				border-radius: 4px;
+				display: inline-block;
+				margin-left: 0.5em;
+				padding: 0 0.5em;
+			}
+
+				#nav > ul > li a {
+					color: inherit;
+					line-height: 4em;
+					letter-spacing: 2px;
+					text-decoration: none;
+					text-transform: uppercase;
+					font-weight: 400;
+					font-size: 1em;
+				}
+
+				#nav > ul > li:first-child {
+					margin-left: 0;
+				}
+
+				#nav > ul > li.active a {
+					color: white;
+				}
+
+				#nav > ul > li > ul {
+					display: none;
+				}
+
+/* Dropotron */
+
+	.dropotron {
+		top: 2em;
+		background: rgba(32, 32, 32, 0.75);
+		border-radius: 4px;
+		color: inherit;
+		min-width: 12em;
+		padding: 1em 0;
+		color: white;
+	}
+
+		.dropotron > li {
+			line-height: 2em;
+			padding: 0 1em;
+		}
+
+			.dropotron > li > a {
+				color: inherit;
+				letter-spacing: 2px;
+				text-decoration: none;
+				text-transform: uppercase;
+			}
+
+			.dropotron > li.active > a, .dropotron > li:hover > a {
+				color: inherit;
+			}
+
+		.dropotron.level-0 {
+			border-radius: 0 0 4px 4px;
+			font-size: 1em;
+			margin-left: -0.5em;
+		}
+
+/* Banner */
+
+	#banner {
+		padding: 6em 0em 3em 0em;
+		text-align: center;
+		text-transform: uppercase;
+		color: white;
+	}
+
+		#banner .container {
+			padding: 0em 8em;
+		}
+
+		#banner h2 {
+			display: inline-block;
+			padding: 0.50em 0.30em;
+			background: #82b440;
+			font-size: 3em;
+			font-weight: 400;
+		}
+
+		#banner span, #banner p {
+			display: block;
+			letter-spacing: 1px;
+			text-transform: uppercase;
+			font-size: 1.6em;
+			font-weight: 300;
+		}
+
+		#banner span {
+			padding: 1em 0em;
+		}
+
+/* Main */
+
+	#main {
+		padding: 4em 0;
+	}
+
+		#main #content .major, #main #sidebar .major {
+			text-align: left;
+		}
+
+		#main #sidebar section {
+			margin-top: 4em;
+		}
+
+			#main #sidebar section:first-child {
+				margin-top: 0;
+			}
+
+		#main #sidebar .major {
+			padding-bottom: 2em;
+		}
+
+			#main #sidebar .major h2 {
+				font-size: 1.8em;
+			}
+
+/* Footer */
+
+	#footer {
+		padding: 6em 0 2em 0;
+		text-align: center;
+		color: white;
+	}
+
+		#footer hr {
+			border-bottom: 1px solid;
+			border-color: inherit;
+			opacity: .05;
+		}
+
+		#footer .major h2 {
+			color: inherit;
+		}
+
+		#footer .major .byline {
+			color: inherit;
+			opacity: .4;
+		}
+
+		#footer .copyright {
+			margin-top: 3em;
+			text-align: center;
+		}
+
+/* Copyright */
+
+	#copyright {
+		position: relative;
+		text-transform: uppercase;
+		text-align: center;
+		padding: 3em 0em 3em 0em;
+		color: inherit;
+		opacity: .40;
+	}
+
+		#copyright a {
+			text-decoration: none;
+			color: inherit;
+		}
+
+/* Extra */
+
+	#extra1 h2 {
+		display: block;
+		margin-bottom: 1em;
+		letter-spacing: 1px;
+		line-height: 1.4em;
+		text-transform: uppercase;
+		font-size: 1.8em;
+		font-weight: 400;
+	}
+
+	#extra1 h3 {
+		display: block;
+		margin-bottom: 1em;
+		letter-spacing: 1px;
+		line-height: 1.4em;
+		text-transform: uppercase;
+		font-size: 1.6em;
+		font-weight: 400;
+	}
+
+/* Team */
+
+	#team h3 {
+		margin-bottom: 0.50em;
+		letter-spacing: 2px;
+		text-transform: uppercase;
+		font-weight: 700;
+	}

+ 261 - 0
api-v12/public/assets/solarize/widgets.css

@@ -0,0 +1,261 @@
+pre.phpdebugbar-widgets-code-block {
+    white-space: pre;
+    word-wrap: normal;
+    overflow: hidden;
+}
+  pre.phpdebugbar-widgets-code-block code {
+    display: block;
+    overflow-x: auto;
+    overflow-y: hidden;
+  }
+  pre.phpdebugbar-widgets-code-block code.phpdebugbar-widgets-numbered-code {
+    padding: 5px;
+  }
+    pre.phpdebugbar-widgets-code-block code span.phpdebugbar-widgets-highlighted-line {
+      background: #800000;
+      color: #fff;
+      display: inline-block;
+      min-width: 100%;
+    }
+      pre.phpdebugbar-widgets-code-block code span.phpdebugbar-widgets-highlighted-line span {
+        background: none !important;
+        color: inherit !important;
+      }
+  pre.phpdebugbar-widgets-code-block ul {
+    float: left;
+    padding: 5px;
+    background: #cacaca;
+    border-right: 1px solid #aaa;
+    text-align: right;
+  }
+
+/* -------------------------------------- */
+
+ul.phpdebugbar-widgets-list {
+  margin: 0;
+  padding: 0;
+  list-style: none;
+  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
+}
+  ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item {
+    padding: 3px 6px;
+    border-bottom: 1px solid #eee;
+    position: relative;
+    overflow: hidden;
+  }
+  ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item:hover {
+    background: #fafafa;
+  }
+
+/* -------------------------------------- */
+
+div.phpdebugbar-widgets-messages {
+  position: relative;
+  height: 100%;
+}
+  div.phpdebugbar-widgets-messages ul.phpdebugbar-widgets-list {
+    padding-bottom: 20px;
+  }
+  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-warning:before {
+    font-family: PhpDebugbarFontAwesome;
+    content: "\f071";
+    margin-right: 8px;
+    font-size: 11px;
+    color: #ecb03d;
+  }
+  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-error {
+    color: red;
+  }
+  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-error:before {
+    font-family: PhpDebugbarFontAwesome;
+    content: "\f057";
+    margin-right: 8px;
+    font-size: 11px;
+    color: red;
+  }
+  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item pre.sf-dump {
+    display: inline;
+  }
+  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-collector,
+  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-label {
+    float: right;
+    font-size: 12px;
+    padding: 2px 4px;
+    color: #888;
+    margin: 0 2px;
+    text-decoration: none;
+    text-shadow: none;
+    background: none;
+    font-weight: normal;
+  }
+  div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-collector {
+    color: #555;
+    font-style: italic;
+  }
+  div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar {
+    position: fixed;
+    bottom: 0;
+    width: 100%;
+    background: #fff;
+  }
+    div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar input {
+      border: 0;
+      margin: 0;
+      margin-left: 7px;
+      width: 50%;
+      box-shadow: none;
+    }
+    div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar input:focus {
+      outline: none;
+    }
+      div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter {
+        float: right;
+        font-size: 12px;
+        padding: 2px 4px;
+        background: #7cacd5;
+        margin: 0 2px;
+        border-radius: 4px;
+        color: #fff;
+        text-decoration: none;
+      }
+      div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter.phpdebugbar-widgets-excluded {
+        background: #eee;
+        color: #888;
+      }
+
+/* -------------------------------------- */
+
+dl.phpdebugbar-widgets-kvlist {
+  margin: 0;
+}
+  dl.phpdebugbar-widgets-kvlist dt {
+    float: left;
+    width: 150px;
+    padding: 5px;
+    border-top: 1px solid #eee;
+    font-weight: bold;
+    clear: both;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+  dl.phpdebugbar-widgets-kvlist dd {
+    margin-left: 160px;
+    padding: 5px;
+    border-top: 1px solid #eee;
+    cursor: pointer;
+    min-height: 17px;
+  }
+
+/* -------------------------------------- */
+
+dl.phpdebugbar-widgets-varlist,
+dl.phpdebugbar-widgets-htmlvarlist {
+  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
+}
+  dl.phpdebugbar-widgets-htmlvarlist dd {
+    cursor: initial;
+  }
+
+/* -------------------------------------- */
+
+ul.phpdebugbar-widgets-timeline {
+  margin: 0;
+  padding: 0;
+  list-style: none;
+}
+  ul.phpdebugbar-widgets-timeline .phpdebugbar-widgets-measure {
+    height: 20px;
+    position: relative;
+    border-bottom: 1px solid #eee;
+    display: block;
+  }
+  ul.phpdebugbar-widgets-timeline li:hover {
+    background: #fafafa;
+  }
+    ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-label,
+    ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-collector {
+      position: absolute;
+      font-size: 12px;
+      font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
+      color: #555;
+      top: 4px;
+      left: 5px;
+      background: none;
+      text-shadow: none;
+      font-weight: normal;
+      white-space: pre;
+    }
+    ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-collector {
+      left: initial;
+      right: 5px;
+    }
+    ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-value {
+      display: block;
+      position: absolute;
+      height: 10px;
+      background: #3db9ec;
+      top: 5px;
+      border-radius: 2px;
+      min-width: 1px;
+    }
+    ul.phpdebugbar-widgets-timeline table.phpdebugbar-widgets-params {
+      display: none;
+      width: 70%;
+      margin: 10px;
+      border: 1px solid #ddd;
+      font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
+      border-collapse: collapse;
+    }
+      ul.phpdebugbar-widgets-timeline table.phpdebugbar-widgets-params td {
+        border: 1px solid #ddd;
+        padding: 0 5px;
+      }
+      ul.phpdebugbar-widgets-timeline table.phpdebugbar-widgets-params .phpdebugbar-widgets-name {
+        width: 20%;
+        font-weight: bold;
+      }
+
+/* -------------------------------------- */
+
+div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item {
+  cursor: pointer;
+}
+  div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-message {
+    display: block;
+    color: red;
+  }
+
+  div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-filename {
+    display: block;
+    font-style: italic;
+    color: #555;
+  }
+
+  div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-type {
+    display: block;
+    position: absolute;
+    right: 4px;
+    top: 4px;
+    font-weight: bold;
+  }
+
+  div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item pre.phpdebugbar-widgets-file {
+    display: none;
+    margin: 10px;
+    padding: 5px;
+    border: 1px solid #ddd;
+    font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
+  }
+
+div.phpdebugbar-widgets-exceptions a.phpdebugbar-widgets-editor-link:before {
+  font-family: PhpDebugbarFontAwesome;
+  margin-right: 4px;
+  font-size: 12px;
+  font-style: normal;
+}
+
+div.phpdebugbar-widgets-exceptions a.phpdebugbar-widgets-editor-link:before {
+  content: "\f08e";
+  margin-left: 4px;
+}

+ 589 - 0
api-v12/public/assets/solarize/widgets.js

@@ -0,0 +1,589 @@
+if (typeof(PhpDebugBar) == 'undefined') {
+    // namespace
+    var PhpDebugBar = {};
+    PhpDebugBar.$ = jQuery;
+}
+
+(function($) {
+
+    /**
+     * @namespace
+     */
+    PhpDebugBar.Widgets = {};
+
+    var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-widgets-');
+
+    /**
+     * Replaces spaces with &nbsp; and line breaks with <br>
+     *
+     * @param {String} text
+     * @return {String}
+     */
+    var htmlize = PhpDebugBar.Widgets.htmlize = function(text) {
+        return text.replace(/\n/g, '<br>').replace(/\s/g, "&nbsp;")
+    };
+
+    /**
+     * Returns a string representation of value, using JSON.stringify
+     * if it's an object.
+     *
+     * @param {Object} value
+     * @param {Boolean} prettify Uses htmlize() if true
+     * @return {String}
+     */
+    var renderValue = PhpDebugBar.Widgets.renderValue = function(value, prettify) {
+        if (typeof(value) !== 'string') {
+            if (prettify) {
+                return htmlize(JSON.stringify(value, undefined, 2));
+            }
+            return JSON.stringify(value);
+        }
+        return value;
+    };
+
+    /**
+     * Highlights a block of code
+     *
+     * @param  {String} code
+     * @param  {String} lang
+     * @return {String}
+     */
+    var highlight = PhpDebugBar.Widgets.highlight = function(code, lang) {
+        if (typeof(code) === 'string') {
+            if (typeof(hljs) === 'undefined') {
+                return htmlize(code);
+            }
+            if (lang) {
+                return hljs.highlight(lang, code).value;
+            }
+            return hljs.highlightAuto(code).value;
+        }
+
+        if (typeof(hljs) === 'object') {
+            code.each(function(i, e) { hljs.highlightBlock(e); });
+        }
+        return code;
+    };
+
+    /**
+     * Creates a <pre> element with a block of code
+     *
+     * @param  {String} code
+     * @param  {String} lang
+     * @param  {Number} [firstLineNumber] If provided, shows line numbers beginning with the given value.
+     * @param  {Number} [highlightedLine] If provided, the given line number will be highlighted.
+     * @return {String}
+     */
+    var createCodeBlock = PhpDebugBar.Widgets.createCodeBlock = function(code, lang, firstLineNumber, highlightedLine) {
+        var pre = $('<pre />').addClass(csscls('code-block'));
+        // Add a newline to prevent <code> element from vertically collapsing too far if the last
+        // code line was empty: that creates problems with the horizontal scrollbar being
+        // incorrectly positioned - most noticeable when line numbers are shown.
+        var codeElement = $('<code />').text(code + '\n').appendTo(pre);
+
+        // Add a span with a special class if we are supposed to highlight a line.  highlight.js will
+        // still correctly format code even with existing markup in it.
+        if ($.isNumeric(highlightedLine)) {
+            if ($.isNumeric(firstLineNumber)) {
+                highlightedLine = highlightedLine - firstLineNumber + 1;
+            }
+            codeElement.html(function (index, html) {
+                var currentLine = 1;
+                return html.replace(/^.*$/gm, function(line) {
+                    if (currentLine++ == highlightedLine) {
+                        return '<span class="' + csscls('highlighted-line') + '">' + line + '</span>';
+                    } else {
+                        return line;
+                    }
+                });
+            });
+        }
+
+        // Format the code
+        if (lang) {
+            pre.addClass("language-" + lang);
+        }
+        highlight(pre);
+
+        // Show line numbers in a list
+        if ($.isNumeric(firstLineNumber)) {
+            var lineCount = code.split('\n').length;
+            var $lineNumbers = $('<ul />').prependTo(pre);
+            pre.children().addClass(csscls('numbered-code'));
+            for (var i = firstLineNumber; i < firstLineNumber + lineCount; i++) {
+                $('<li />').text(i).appendTo($lineNumbers);
+            }
+        }
+
+        return pre;
+    };
+
+    // ------------------------------------------------------------------
+    // Generic widgets
+    // ------------------------------------------------------------------
+
+    /**
+     * Displays array element in a <ul> list
+     *
+     * Options:
+     *  - data
+     *  - itemRenderer: a function used to render list items (optional)
+     */
+    var ListWidget = PhpDebugBar.Widgets.ListWidget = PhpDebugBar.Widget.extend({
+
+        tagName: 'ul',
+
+        className: csscls('list'),
+
+        initialize: function(options) {
+            if (!options['itemRenderer']) {
+                options['itemRenderer'] = this.itemRenderer;
+            }
+            this.set(options);
+        },
+
+        render: function() {
+            this.bindAttr(['itemRenderer', 'data'], function() {
+                this.$el.empty();
+                if (!this.has('data')) {
+                    return;
+                }
+
+                var data = this.get('data');
+                for (var i = 0; i < data.length; i++) {
+                    var li = $('<li />').addClass(csscls('list-item')).appendTo(this.$el);
+                    this.get('itemRenderer')(li, data[i]);
+                }
+            });
+        },
+
+        /**
+         * Renders the content of a <li> element
+         *
+         * @param {jQuery} li The <li> element as a jQuery Object
+         * @param {Object} value An item from the data array
+         */
+        itemRenderer: function(li, value) {
+            li.html(renderValue(value));
+        }
+
+    });
+
+    // ------------------------------------------------------------------
+
+    /**
+     * Displays object property/value paris in a <dl> list
+     *
+     * Options:
+     *  - data
+     *  - itemRenderer: a function used to render list items (optional)
+     */
+    var KVListWidget = PhpDebugBar.Widgets.KVListWidget = ListWidget.extend({
+
+        tagName: 'dl',
+
+        className: csscls('kvlist'),
+
+        render: function() {
+            this.bindAttr(['itemRenderer', 'data'], function() {
+                this.$el.empty();
+                if (!this.has('data')) {
+                    return;
+                }
+
+                var self = this;
+                $.each(this.get('data'), function(key, value) {
+                    var dt = $('<dt />').addClass(csscls('key')).appendTo(self.$el);
+                    var dd = $('<dd />').addClass(csscls('value')).appendTo(self.$el);
+                    self.get('itemRenderer')(dt, dd, key, value);
+                });
+            });
+        },
+
+        /**
+         * Renders the content of the <dt> and <dd> elements
+         *
+         * @param {jQuery} dt The <dt> element as a jQuery Object
+         * @param {jQuery} dd The <dd> element as a jQuery Object
+         * @param {String} key Property name
+         * @param {Object} value Property value
+         */
+        itemRenderer: function(dt, dd, key, value) {
+            dt.text(key);
+            dd.html(htmlize(value));
+        }
+
+    });
+
+    // ------------------------------------------------------------------
+
+    /**
+     * An extension of KVListWidget where the data represents a list
+     * of variables
+     *
+     * Options:
+     *  - data
+     */
+    var VariableListWidget = PhpDebugBar.Widgets.VariableListWidget = KVListWidget.extend({
+
+        className: csscls('kvlist varlist'),
+
+        itemRenderer: function(dt, dd, key, value) {
+            $('<span />').attr('title', key).text(key).appendTo(dt);
+
+            var v = value;
+            if (v && v.length > 100) {
+                v = v.substr(0, 100) + "...";
+            }
+            var prettyVal = null;
+            dd.text(v).click(function() {
+                if (dd.hasClass(csscls('pretty'))) {
+                    dd.text(v).removeClass(csscls('pretty'));
+                } else {
+                    prettyVal = prettyVal || createCodeBlock(value);
+                    dd.addClass(csscls('pretty')).empty().append(prettyVal);
+                }
+            });
+        }
+
+    });
+
+    // ------------------------------------------------------------------
+
+    /**
+     * An extension of KVListWidget where the data represents a list
+     * of variables whose contents are HTML; this is useful for showing
+     * variable output from VarDumper's HtmlDumper.
+     *
+     * Options:
+     *  - data
+     */
+    var HtmlVariableListWidget = PhpDebugBar.Widgets.HtmlVariableListWidget = KVListWidget.extend({
+
+        className: csscls('kvlist htmlvarlist'),
+
+        itemRenderer: function(dt, dd, key, value) {
+            $('<span />').attr('title', key).text(key).appendTo(dt);
+            dd.html(value);
+        }
+
+    });
+
+    // ------------------------------------------------------------------
+
+    /**
+     * Iframe widget
+     *
+     * Options:
+     *  - data
+     */
+    var IFrameWidget = PhpDebugBar.Widgets.IFrameWidget = PhpDebugBar.Widget.extend({
+
+        tagName: 'iframe',
+
+        className: csscls('iframe'),
+
+        render: function() {
+            this.$el.attr({
+                seamless: "seamless",
+                border: "0",
+                width: "100%",
+                height: "100%"
+            });
+            this.bindAttr('data', function(url) { this.$el.attr('src', url); });
+        }
+
+    });
+
+
+    // ------------------------------------------------------------------
+    // Collector specific widgets
+    // ------------------------------------------------------------------
+
+    /**
+     * Widget for the MessagesCollector
+     *
+     * Uses ListWidget under the hood
+     *
+     * Options:
+     *  - data
+     */
+    var MessagesWidget = PhpDebugBar.Widgets.MessagesWidget = PhpDebugBar.Widget.extend({
+
+        className: csscls('messages'),
+
+        render: function() {
+            var self = this;
+
+            this.$list = new ListWidget({ itemRenderer: function(li, value) {
+                if (value.message_html) {
+                    var val = $('<span />').addClass(csscls('value')).html(value.message_html).appendTo(li);
+                } else {
+                    var m = value.message;
+                    if (m.length > 100) {
+                        m = m.substr(0, 100) + "...";
+                    }
+
+                    var val = $('<span />').addClass(csscls('value')).text(m).appendTo(li);
+                    if (!value.is_string || value.message.length > 100) {
+                        var prettyVal = value.message;
+                        if (!value.is_string) {
+                            prettyVal = null;
+                        }
+                        li.css('cursor', 'pointer').click(function () {
+                            if (val.hasClass(csscls('pretty'))) {
+                                val.text(m).removeClass(csscls('pretty'));
+                            } else {
+                                prettyVal = prettyVal || createCodeBlock(value.message, 'php');
+                                val.addClass(csscls('pretty')).empty().append(prettyVal);
+                            }
+                        });
+                    }
+                }
+
+                if (value.collector) {
+                    $('<span />').addClass(csscls('collector')).text(value.collector).prependTo(li);
+                }
+                if (value.label) {
+                    val.addClass(csscls(value.label));
+                    $('<span />').addClass(csscls('label')).text(value.label).prependTo(li);
+                }
+            }});
+
+            this.$list.$el.appendTo(this.$el);
+            this.$toolbar = $('<div><i class="phpdebugbar-fa phpdebugbar-fa-search"></i></div>').addClass(csscls('toolbar')).appendTo(this.$el);
+
+            $('<input type="text" />')
+                .on('change', function() { self.set('search', this.value); })
+                .appendTo(this.$toolbar);
+
+            this.bindAttr('data', function(data) {
+                this.set({ exclude: [], search: '' });
+                this.$toolbar.find(csscls('.filter')).remove();
+
+                var filters = [], self = this;
+                for (var i = 0; i < data.length; i++) {
+                    if (!data[i].label || $.inArray(data[i].label, filters) > -1) {
+                        continue;
+                    }
+                    filters.push(data[i].label);
+                    $('<a />')
+                        .addClass(csscls('filter'))
+                        .text(data[i].label)
+                        .attr('rel', data[i].label)
+                        .on('click', function() { self.onFilterClick(this); })
+                        .appendTo(this.$toolbar);
+                }
+            });
+
+            this.bindAttr(['exclude', 'search'], function() {
+                var data = this.get('data'),
+                    exclude = this.get('exclude'),
+                    search = this.get('search'),
+                    caseless = false,
+                    fdata = [];
+
+                if (search && search === search.toLowerCase()) {
+                    caseless = true;
+                }
+
+                for (var i = 0; i < data.length; i++) {
+                    var message = caseless ? data[i].message.toLowerCase() : data[i].message;
+
+                    if ((!data[i].label || $.inArray(data[i].label, exclude) === -1) && (!search || message.indexOf(search) > -1)) {
+                        fdata.push(data[i]);
+                    }
+                }
+
+                this.$list.set('data', fdata);
+            });
+        },
+
+        onFilterClick: function(el) {
+            $(el).toggleClass(csscls('excluded'));
+
+            var excludedLabels = [];
+            this.$toolbar.find(csscls('.filter') + csscls('.excluded')).each(function() {
+                excludedLabels.push(this.rel);
+            });
+
+            this.set('exclude', excludedLabels);
+        }
+
+    });
+
+    // ------------------------------------------------------------------
+
+    /**
+     * Widget for the TimeDataCollector
+     *
+     * Options:
+     *  - data
+     */
+    var TimelineWidget = PhpDebugBar.Widgets.TimelineWidget = PhpDebugBar.Widget.extend({
+
+        tagName: 'ul',
+
+        className: csscls('timeline'),
+
+        render: function() {
+            this.bindAttr('data', function(data) {
+
+                // ported from php DataFormatter
+                var formatDuration = function(seconds) {
+                    if (seconds < 0.001)
+                        return (seconds * 1000000).toFixed() + 'μs';
+                    else if (seconds < 1)
+                        return (seconds * 1000).toFixed(2) + 'ms';
+                    return (seconds).toFixed(2) +  's';
+                };
+
+                this.$el.empty();
+                if (data.measures) {
+                    var aggregate = {};
+
+                    for (var i = 0; i < data.measures.length; i++) {
+                        var measure = data.measures[i];
+
+                        if(!aggregate[measure.label])
+                            aggregate[measure.label] = { count: 0, duration: 0 };
+
+                        aggregate[measure.label]['count'] += 1;
+                        aggregate[measure.label]['duration'] += measure.duration;
+
+                        var m = $('<div />').addClass(csscls('measure')),
+                            li = $('<li />'),
+                            left = (measure.relative_start * 100 / data.duration).toFixed(2),
+                            width = Math.min((measure.duration * 100 / data.duration).toFixed(2), 100 - left);
+
+                        m.append($('<span />').addClass(csscls('value')).css({
+                            left: left + "%",
+                            width: width + "%"
+                        }));
+                        m.append($('<span />').addClass(csscls('label')).text(measure.label + " (" + measure.duration_str + ")"));
+
+                        if (measure.collector) {
+                            $('<span />').addClass(csscls('collector')).text(measure.collector).appendTo(m);
+                        }
+
+                        m.appendTo(li);
+                        this.$el.append(li);
+
+                        if (measure.params && !$.isEmptyObject(measure.params)) {
+                            var table = $('<table><tr><th colspan="2">Params</th></tr></table>').addClass(csscls('params')).appendTo(li);
+                            for (var key in measure.params) {
+                                if (typeof measure.params[key] !== 'function') {
+                                    table.append('<tr><td class="' + csscls('name') + '">' + key + '</td><td class="' + csscls('value') +
+                                    '"><pre><code>' + measure.params[key] + '</code></pre></td></tr>');
+                                }
+                            }
+                            li.css('cursor', 'pointer').click(function() {
+                                var table = $(this).find('table');
+                                if (table.is(':visible')) {
+                                    table.hide();
+                                } else {
+                                    table.show();
+                                }
+                            });
+                        }
+                    }
+
+                    // convert to array and sort by duration
+                    aggregate = $.map(aggregate, function(data, label) {
+                       return {
+                           label: label,
+                           data: data
+                       }
+                    }).sort(function(a, b) {
+                        return b.data.duration - a.data.duration
+                    });
+
+                    // build table and add
+                    var aggregateTable = $('<table style="display: table; border: 0; width: 99%"></table>').addClass(csscls('params'));
+                    $.each(aggregate, function(i, aggregate) {
+                        width = Math.min((aggregate.data.duration * 100 / data.duration).toFixed(2), 100);
+
+                        aggregateTable.append('<tr><td class="' + csscls('name') + '">' + aggregate.data.count + ' x ' + aggregate.label + ' (' + width + '%)</td><td class="' + csscls('value') + '">' +
+                            '<div class="' + csscls('measure') +'">' +
+                                '<span class="' + csscls('value') + '" style="width:' + width + '%"></span>' +
+                                '<span class="' + csscls('label') + '">' + formatDuration(aggregate.data.duration) + '</span>' +
+                            '</div></td></tr>');
+                    });
+
+                    this.$el.append('<li/>').find('li:last').append(aggregateTable);
+                }
+            });
+        }
+
+    });
+
+    // ------------------------------------------------------------------
+
+    /**
+     * Widget for the displaying exceptions
+     *
+     * Options:
+     *  - data
+     */
+    var ExceptionsWidget = PhpDebugBar.Widgets.ExceptionsWidget = PhpDebugBar.Widget.extend({
+
+        className: csscls('exceptions'),
+
+        render: function() {
+            this.$list = new ListWidget({ itemRenderer: function(li, e) {
+                $('<span />').addClass(csscls('message')).text(e.message).appendTo(li);
+                if (e.file) {
+                    var header = $('<span />').addClass(csscls('filename')).text(e.file + "#" + e.line);
+                    if (e.xdebug_link) {
+                        if (e.xdebug_link.ajax) {
+                            $('<a title="' + e.xdebug_link.url + '"></a>').on('click', function () {
+                                $.ajax(e.xdebug_link.url);
+                            }).addClass(csscls('editor-link')).appendTo(header);
+                        } else {
+                            $('<a href="' + e.xdebug_link.url + '"></a>').addClass(csscls('editor-link')).appendTo(header);
+                        }
+                    }
+                    header.appendTo(li);
+                }
+                if (e.type) {
+                    $('<span />').addClass(csscls('type')).text(e.type).appendTo(li);
+                }
+                if (e.surrounding_lines) {
+                    var pre = createCodeBlock(e.surrounding_lines.join(""), 'php').addClass(csscls('file')).appendTo(li);
+                    if (!e.stack_trace_html) {
+                        // This click event makes the var-dumper hard to use.
+                        li.click(function () {
+                            if (pre.is(':visible')) {
+                                pre.hide();
+                            } else {
+                                pre.show();
+                            }
+                        });
+                    }
+                }
+                if (e.stack_trace_html) {
+                    var $trace = $('<span />').addClass(csscls('filename')).html(e.stack_trace_html);
+                    $trace.appendTo(li);
+                } else if (e.stack_trace) {
+                    e.stack_trace.split("\n").forEach(function (trace) {
+                        var $traceLine = $('<div />');
+                        $('<span />').addClass(csscls('filename')).text(trace).appendTo($traceLine);
+                        $traceLine.appendTo(li);
+                    });
+                }
+            }});
+            this.$list.$el.appendTo(this.$el);
+
+            this.bindAttr('data', function(data) {
+                this.$list.set('data', data);
+                if (data.length == 1) {
+                    this.$list.$el.children().first().find(csscls('.file')).show();
+                }
+            });
+
+        }
+
+    });
+
+
+})(PhpDebugBar.$);

Різницю між файлами не показано, бо вона завелика
+ 0 - 0
api-v12/public/assets/typhoon/css/form-styles.css


Різницю між файлами не показано, бо вона завелика
+ 0 - 0
api-v12/public/assets/typhoon/css/glightbox.min.css


+ 1 - 0
api-v12/public/assets/typhoon/css/notices.css

@@ -0,0 +1 @@
+.notices{padding:1px 1px 1px 30px;margin:15px 0}.notices p{}.notices.yellow{border-left:10px solid #f0ad4e;background:#fcf8f2;color:#df8a13}.notices.red{border-left:10px solid #d9534f;background:#fdf7f7;color:#b52b27}.notices.blue{border-left:10px solid #5bc0de;background:#f4f8fa;color:#28a1c5}.notices.green{border-left:10px solid #5cb85c;background:#f1f9f1;color:#3d8b3d}

Різницю між файлами не показано, бо вона завелика
+ 0 - 0
api-v12/public/assets/typhoon/css/site.css


+ 1956 - 0
api-v12/public/assets/typhoon/js/alpine.js

@@ -0,0 +1,1956 @@
+(function (global, factory) {
+  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+  typeof define === 'function' && define.amd ? define(factory) :
+  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Alpine = factory());
+}(this, (function () { 'use strict';
+
+  function _defineProperty(obj, key, value) {
+    if (key in obj) {
+      Object.defineProperty(obj, key, {
+        value: value,
+        enumerable: true,
+        configurable: true,
+        writable: true
+      });
+    } else {
+      obj[key] = value;
+    }
+
+    return obj;
+  }
+
+  function ownKeys(object, enumerableOnly) {
+    var keys = Object.keys(object);
+
+    if (Object.getOwnPropertySymbols) {
+      var symbols = Object.getOwnPropertySymbols(object);
+      if (enumerableOnly) symbols = symbols.filter(function (sym) {
+        return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+      });
+      keys.push.apply(keys, symbols);
+    }
+
+    return keys;
+  }
+
+  function _objectSpread2(target) {
+    for (var i = 1; i < arguments.length; i++) {
+      var source = arguments[i] != null ? arguments[i] : {};
+
+      if (i % 2) {
+        ownKeys(Object(source), true).forEach(function (key) {
+          _defineProperty(target, key, source[key]);
+        });
+      } else if (Object.getOwnPropertyDescriptors) {
+        Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
+      } else {
+        ownKeys(Object(source)).forEach(function (key) {
+          Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
+        });
+      }
+    }
+
+    return target;
+  }
+
+  // Thanks @stimulus:
+  // https://github.com/stimulusjs/stimulus/blob/master/packages/%40stimulus/core/src/application.ts
+  function domReady() {
+    return new Promise(resolve => {
+      if (document.readyState == "loading") {
+        document.addEventListener("DOMContentLoaded", resolve);
+      } else {
+        resolve();
+      }
+    });
+  }
+  function arrayUnique(array) {
+    return Array.from(new Set(array));
+  }
+  function isTesting() {
+    return navigator.userAgent.includes("Node.js") || navigator.userAgent.includes("jsdom");
+  }
+  function checkedAttrLooseCompare(valueA, valueB) {
+    return valueA == valueB;
+  }
+  function warnIfMalformedTemplate(el, directive) {
+    if (el.tagName.toLowerCase() !== 'template') {
+      console.warn(`Alpine: [${directive}] directive should only be added to <template> tags. See https://github.com/alpinejs/alpine#${directive}`);
+    } else if (el.content.childElementCount !== 1) {
+      console.warn(`Alpine: <template> tag with [${directive}] encountered with an unexpected number of root elements. Make sure <template> has a single root element. `);
+    }
+  }
+  function kebabCase(subject) {
+    return subject.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/[_\s]/, '-').toLowerCase();
+  }
+  function camelCase(subject) {
+    return subject.toLowerCase().replace(/-(\w)/g, (match, char) => char.toUpperCase());
+  }
+  function walk(el, callback) {
+    if (callback(el) === false) return;
+    let node = el.firstElementChild;
+
+    while (node) {
+      walk(node, callback);
+      node = node.nextElementSibling;
+    }
+  }
+  function debounce(func, wait) {
+    var timeout;
+    return function () {
+      var context = this,
+          args = arguments;
+
+      var later = function later() {
+        timeout = null;
+        func.apply(context, args);
+      };
+
+      clearTimeout(timeout);
+      timeout = setTimeout(later, wait);
+    };
+  }
+
+  const handleError = (el, expression, error) => {
+    console.warn(`Alpine Error: "${error}"\n\nExpression: "${expression}"\nElement:`, el);
+
+    if (!isTesting()) {
+      Object.assign(error, {
+        el,
+        expression
+      });
+      throw error;
+    }
+  };
+
+  function tryCatch(cb, {
+    el,
+    expression
+  }) {
+    try {
+      const value = cb();
+      return value instanceof Promise ? value.catch(e => handleError(el, expression, e)) : value;
+    } catch (e) {
+      handleError(el, expression, e);
+    }
+  }
+
+  function saferEval(el, expression, dataContext, additionalHelperVariables = {}) {
+    return tryCatch(() => {
+      if (typeof expression === 'function') {
+        return expression.call(dataContext);
+      }
+
+      return new Function(['$data', ...Object.keys(additionalHelperVariables)], `var __alpine_result; with($data) { __alpine_result = ${expression} }; return __alpine_result`)(dataContext, ...Object.values(additionalHelperVariables));
+    }, {
+      el,
+      expression
+    });
+  }
+  function saferEvalNoReturn(el, expression, dataContext, additionalHelperVariables = {}) {
+    return tryCatch(() => {
+      if (typeof expression === 'function') {
+        return Promise.resolve(expression.call(dataContext, additionalHelperVariables['$event']));
+      }
+
+      let AsyncFunction = Function;
+      /* MODERN-ONLY:START */
+
+      AsyncFunction = Object.getPrototypeOf(async function () {}).constructor;
+      /* MODERN-ONLY:END */
+      // For the cases when users pass only a function reference to the caller: `x-on:click="foo"`
+      // Where "foo" is a function. Also, we'll pass the function the event instance when we call it.
+
+      if (Object.keys(dataContext).includes(expression)) {
+        let methodReference = new Function(['dataContext', ...Object.keys(additionalHelperVariables)], `with(dataContext) { return ${expression} }`)(dataContext, ...Object.values(additionalHelperVariables));
+
+        if (typeof methodReference === 'function') {
+          return Promise.resolve(methodReference.call(dataContext, additionalHelperVariables['$event']));
+        } else {
+          return Promise.resolve();
+        }
+      }
+
+      return Promise.resolve(new AsyncFunction(['dataContext', ...Object.keys(additionalHelperVariables)], `with(dataContext) { ${expression} }`)(dataContext, ...Object.values(additionalHelperVariables)));
+    }, {
+      el,
+      expression
+    });
+  }
+  const xAttrRE = /^x-(on|bind|data|text|html|model|if|for|show|cloak|transition|ref|spread)\b/;
+  function isXAttr(attr) {
+    const name = replaceAtAndColonWithStandardSyntax(attr.name);
+    return xAttrRE.test(name);
+  }
+  function getXAttrs(el, component, type) {
+    let directives = Array.from(el.attributes).filter(isXAttr).map(parseHtmlAttribute); // Get an object of directives from x-spread.
+
+    let spreadDirective = directives.filter(directive => directive.type === 'spread')[0];
+
+    if (spreadDirective) {
+      let spreadObject = saferEval(el, spreadDirective.expression, component.$data); // Add x-spread directives to the pile of existing directives.
+
+      directives = directives.concat(Object.entries(spreadObject).map(([name, value]) => parseHtmlAttribute({
+        name,
+        value
+      })));
+    }
+
+    if (type) return directives.filter(i => i.type === type);
+    return sortDirectives(directives);
+  }
+
+  function sortDirectives(directives) {
+    let directiveOrder = ['bind', 'model', 'show', 'catch-all'];
+    return directives.sort((a, b) => {
+      let typeA = directiveOrder.indexOf(a.type) === -1 ? 'catch-all' : a.type;
+      let typeB = directiveOrder.indexOf(b.type) === -1 ? 'catch-all' : b.type;
+      return directiveOrder.indexOf(typeA) - directiveOrder.indexOf(typeB);
+    });
+  }
+
+  function parseHtmlAttribute({
+    name,
+    value
+  }) {
+    const normalizedName = replaceAtAndColonWithStandardSyntax(name);
+    const typeMatch = normalizedName.match(xAttrRE);
+    const valueMatch = normalizedName.match(/:([a-zA-Z0-9\-:]+)/);
+    const modifiers = normalizedName.match(/\.[^.\]]+(?=[^\]]*$)/g) || [];
+    return {
+      type: typeMatch ? typeMatch[1] : null,
+      value: valueMatch ? valueMatch[1] : null,
+      modifiers: modifiers.map(i => i.replace('.', '')),
+      expression: value
+    };
+  }
+  function isBooleanAttr(attrName) {
+    // As per HTML spec table https://html.spec.whatwg.org/multipage/indices.html#attributes-3:boolean-attribute
+    // Array roughly ordered by estimated usage
+    const booleanAttributes = ['disabled', 'checked', 'required', 'readonly', 'hidden', 'open', 'selected', 'autofocus', 'itemscope', 'multiple', 'novalidate', 'allowfullscreen', 'allowpaymentrequest', 'formnovalidate', 'autoplay', 'controls', 'loop', 'muted', 'playsinline', 'default', 'ismap', 'reversed', 'async', 'defer', 'nomodule'];
+    return booleanAttributes.includes(attrName);
+  }
+  function replaceAtAndColonWithStandardSyntax(name) {
+    if (name.startsWith('@')) {
+      return name.replace('@', 'x-on:');
+    } else if (name.startsWith(':')) {
+      return name.replace(':', 'x-bind:');
+    }
+
+    return name;
+  }
+  function convertClassStringToArray(classList, filterFn = Boolean) {
+    return classList.split(' ').filter(filterFn);
+  }
+  const TRANSITION_TYPE_IN = 'in';
+  const TRANSITION_TYPE_OUT = 'out';
+  const TRANSITION_CANCELLED = 'cancelled';
+  function transitionIn(el, show, reject, component, forceSkip = false) {
+    // We don't want to transition on the initial page load.
+    if (forceSkip) return show();
+
+    if (el.__x_transition && el.__x_transition.type === TRANSITION_TYPE_IN) {
+      // there is already a similar transition going on, this was probably triggered by
+      // a change in a different property, let's just leave the previous one doing its job
+      return;
+    }
+
+    const attrs = getXAttrs(el, component, 'transition');
+    const showAttr = getXAttrs(el, component, 'show')[0]; // If this is triggered by a x-show.transition.
+
+    if (showAttr && showAttr.modifiers.includes('transition')) {
+      let modifiers = showAttr.modifiers; // If x-show.transition.out, we'll skip the "in" transition.
+
+      if (modifiers.includes('out') && !modifiers.includes('in')) return show();
+      const settingBothSidesOfTransition = modifiers.includes('in') && modifiers.includes('out'); // If x-show.transition.in...out... only use "in" related modifiers for this transition.
+
+      modifiers = settingBothSidesOfTransition ? modifiers.filter((i, index) => index < modifiers.indexOf('out')) : modifiers;
+      transitionHelperIn(el, modifiers, show, reject); // Otherwise, we can assume x-transition:enter.
+    } else if (attrs.some(attr => ['enter', 'enter-start', 'enter-end'].includes(attr.value))) {
+      transitionClassesIn(el, component, attrs, show, reject);
+    } else {
+      // If neither, just show that damn thing.
+      show();
+    }
+  }
+  function transitionOut(el, hide, reject, component, forceSkip = false) {
+    // We don't want to transition on the initial page load.
+    if (forceSkip) return hide();
+
+    if (el.__x_transition && el.__x_transition.type === TRANSITION_TYPE_OUT) {
+      // there is already a similar transition going on, this was probably triggered by
+      // a change in a different property, let's just leave the previous one doing its job
+      return;
+    }
+
+    const attrs = getXAttrs(el, component, 'transition');
+    const showAttr = getXAttrs(el, component, 'show')[0];
+
+    if (showAttr && showAttr.modifiers.includes('transition')) {
+      let modifiers = showAttr.modifiers;
+      if (modifiers.includes('in') && !modifiers.includes('out')) return hide();
+      const settingBothSidesOfTransition = modifiers.includes('in') && modifiers.includes('out');
+      modifiers = settingBothSidesOfTransition ? modifiers.filter((i, index) => index > modifiers.indexOf('out')) : modifiers;
+      transitionHelperOut(el, modifiers, settingBothSidesOfTransition, hide, reject);
+    } else if (attrs.some(attr => ['leave', 'leave-start', 'leave-end'].includes(attr.value))) {
+      transitionClassesOut(el, component, attrs, hide, reject);
+    } else {
+      hide();
+    }
+  }
+  function transitionHelperIn(el, modifiers, showCallback, reject) {
+    // Default values inspired by: https://material.io/design/motion/speed.html#duration
+    const styleValues = {
+      duration: modifierValue(modifiers, 'duration', 150),
+      origin: modifierValue(modifiers, 'origin', 'center'),
+      first: {
+        opacity: 0,
+        scale: modifierValue(modifiers, 'scale', 95)
+      },
+      second: {
+        opacity: 1,
+        scale: 100
+      }
+    };
+    transitionHelper(el, modifiers, showCallback, () => {}, reject, styleValues, TRANSITION_TYPE_IN);
+  }
+  function transitionHelperOut(el, modifiers, settingBothSidesOfTransition, hideCallback, reject) {
+    // Make the "out" transition .5x slower than the "in". (Visually better)
+    // HOWEVER, if they explicitly set a duration for the "out" transition,
+    // use that.
+    const duration = settingBothSidesOfTransition ? modifierValue(modifiers, 'duration', 150) : modifierValue(modifiers, 'duration', 150) / 2;
+    const styleValues = {
+      duration: duration,
+      origin: modifierValue(modifiers, 'origin', 'center'),
+      first: {
+        opacity: 1,
+        scale: 100
+      },
+      second: {
+        opacity: 0,
+        scale: modifierValue(modifiers, 'scale', 95)
+      }
+    };
+    transitionHelper(el, modifiers, () => {}, hideCallback, reject, styleValues, TRANSITION_TYPE_OUT);
+  }
+
+  function modifierValue(modifiers, key, fallback) {
+    // If the modifier isn't present, use the default.
+    if (modifiers.indexOf(key) === -1) return fallback; // If it IS present, grab the value after it: x-show.transition.duration.500ms
+
+    const rawValue = modifiers[modifiers.indexOf(key) + 1];
+    if (!rawValue) return fallback;
+
+    if (key === 'scale') {
+      // Check if the very next value is NOT a number and return the fallback.
+      // If x-show.transition.scale, we'll use the default scale value.
+      // That is how a user opts out of the opacity transition.
+      if (!isNumeric(rawValue)) return fallback;
+    }
+
+    if (key === 'duration') {
+      // Support x-show.transition.duration.500ms && duration.500
+      let match = rawValue.match(/([0-9]+)ms/);
+      if (match) return match[1];
+    }
+
+    if (key === 'origin') {
+      // Support chaining origin directions: x-show.transition.top.right
+      if (['top', 'right', 'left', 'center', 'bottom'].includes(modifiers[modifiers.indexOf(key) + 2])) {
+        return [rawValue, modifiers[modifiers.indexOf(key) + 2]].join(' ');
+      }
+    }
+
+    return rawValue;
+  }
+
+  function transitionHelper(el, modifiers, hook1, hook2, reject, styleValues, type) {
+    // clear the previous transition if exists to avoid caching the wrong styles
+    if (el.__x_transition) {
+      el.__x_transition.cancel && el.__x_transition.cancel();
+    } // If the user set these style values, we'll put them back when we're done with them.
+
+
+    const opacityCache = el.style.opacity;
+    const transformCache = el.style.transform;
+    const transformOriginCache = el.style.transformOrigin; // If no modifiers are present: x-show.transition, we'll default to both opacity and scale.
+
+    const noModifiers = !modifiers.includes('opacity') && !modifiers.includes('scale');
+    const transitionOpacity = noModifiers || modifiers.includes('opacity');
+    const transitionScale = noModifiers || modifiers.includes('scale'); // These are the explicit stages of a transition (same stages for in and for out).
+    // This way you can get a birds eye view of the hooks, and the differences
+    // between them.
+
+    const stages = {
+      start() {
+        if (transitionOpacity) el.style.opacity = styleValues.first.opacity;
+        if (transitionScale) el.style.transform = `scale(${styleValues.first.scale / 100})`;
+      },
+
+      during() {
+        if (transitionScale) el.style.transformOrigin = styleValues.origin;
+        el.style.transitionProperty = [transitionOpacity ? `opacity` : ``, transitionScale ? `transform` : ``].join(' ').trim();
+        el.style.transitionDuration = `${styleValues.duration / 1000}s`;
+        el.style.transitionTimingFunction = `cubic-bezier(0.4, 0.0, 0.2, 1)`;
+      },
+
+      show() {
+        hook1();
+      },
+
+      end() {
+        if (transitionOpacity) el.style.opacity = styleValues.second.opacity;
+        if (transitionScale) el.style.transform = `scale(${styleValues.second.scale / 100})`;
+      },
+
+      hide() {
+        hook2();
+      },
+
+      cleanup() {
+        if (transitionOpacity) el.style.opacity = opacityCache;
+        if (transitionScale) el.style.transform = transformCache;
+        if (transitionScale) el.style.transformOrigin = transformOriginCache;
+        el.style.transitionProperty = null;
+        el.style.transitionDuration = null;
+        el.style.transitionTimingFunction = null;
+      }
+
+    };
+    transition(el, stages, type, reject);
+  }
+
+  const ensureStringExpression = (expression, el, component) => {
+    return typeof expression === 'function' ? component.evaluateReturnExpression(el, expression) : expression;
+  };
+
+  function transitionClassesIn(el, component, directives, showCallback, reject) {
+    const enter = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'enter') || {
+      expression: ''
+    }).expression, el, component));
+    const enterStart = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'enter-start') || {
+      expression: ''
+    }).expression, el, component));
+    const enterEnd = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'enter-end') || {
+      expression: ''
+    }).expression, el, component));
+    transitionClasses(el, enter, enterStart, enterEnd, showCallback, () => {}, TRANSITION_TYPE_IN, reject);
+  }
+  function transitionClassesOut(el, component, directives, hideCallback, reject) {
+    const leave = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'leave') || {
+      expression: ''
+    }).expression, el, component));
+    const leaveStart = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'leave-start') || {
+      expression: ''
+    }).expression, el, component));
+    const leaveEnd = convertClassStringToArray(ensureStringExpression((directives.find(i => i.value === 'leave-end') || {
+      expression: ''
+    }).expression, el, component));
+    transitionClasses(el, leave, leaveStart, leaveEnd, () => {}, hideCallback, TRANSITION_TYPE_OUT, reject);
+  }
+  function transitionClasses(el, classesDuring, classesStart, classesEnd, hook1, hook2, type, reject) {
+    // clear the previous transition if exists to avoid caching the wrong classes
+    if (el.__x_transition) {
+      el.__x_transition.cancel && el.__x_transition.cancel();
+    }
+
+    const originalClasses = el.__x_original_classes || [];
+    const stages = {
+      start() {
+        el.classList.add(...classesStart);
+      },
+
+      during() {
+        el.classList.add(...classesDuring);
+      },
+
+      show() {
+        hook1();
+      },
+
+      end() {
+        // Don't remove classes that were in the original class attribute.
+        el.classList.remove(...classesStart.filter(i => !originalClasses.includes(i)));
+        el.classList.add(...classesEnd);
+      },
+
+      hide() {
+        hook2();
+      },
+
+      cleanup() {
+        el.classList.remove(...classesDuring.filter(i => !originalClasses.includes(i)));
+        el.classList.remove(...classesEnd.filter(i => !originalClasses.includes(i)));
+      }
+
+    };
+    transition(el, stages, type, reject);
+  }
+  function transition(el, stages, type, reject) {
+    const finish = once(() => {
+      stages.hide(); // Adding an "isConnected" check, in case the callback
+      // removed the element from the DOM.
+
+      if (el.isConnected) {
+        stages.cleanup();
+      }
+
+      delete el.__x_transition;
+    });
+    el.__x_transition = {
+      // Set transition type so we can avoid clearing transition if the direction is the same
+      type: type,
+      // create a callback for the last stages of the transition so we can call it
+      // from different point and early terminate it. Once will ensure that function
+      // is only called one time.
+      cancel: once(() => {
+        reject(TRANSITION_CANCELLED);
+        finish();
+      }),
+      finish,
+      // This store the next animation frame so we can cancel it
+      nextFrame: null
+    };
+    stages.start();
+    stages.during();
+    el.__x_transition.nextFrame = requestAnimationFrame(() => {
+      // Note: Safari's transitionDuration property will list out comma separated transition durations
+      // for every single transition property. Let's grab the first one and call it a day.
+      let duration = Number(getComputedStyle(el).transitionDuration.replace(/,.*/, '').replace('s', '')) * 1000;
+
+      if (duration === 0) {
+        duration = Number(getComputedStyle(el).animationDuration.replace('s', '')) * 1000;
+      }
+
+      stages.show();
+      el.__x_transition.nextFrame = requestAnimationFrame(() => {
+        stages.end();
+        setTimeout(el.__x_transition.finish, duration);
+      });
+    });
+  }
+  function isNumeric(subject) {
+    return !Array.isArray(subject) && !isNaN(subject);
+  } // Thanks @vuejs
+  // https://github.com/vuejs/vue/blob/4de4649d9637262a9b007720b59f80ac72a5620c/src/shared/util.js
+
+  function once(callback) {
+    let called = false;
+    return function () {
+      if (!called) {
+        called = true;
+        callback.apply(this, arguments);
+      }
+    };
+  }
+
+  function handleForDirective(component, templateEl, expression, initialUpdate, extraVars) {
+    warnIfMalformedTemplate(templateEl, 'x-for');
+    let iteratorNames = typeof expression === 'function' ? parseForExpression(component.evaluateReturnExpression(templateEl, expression)) : parseForExpression(expression);
+    let items = evaluateItemsAndReturnEmptyIfXIfIsPresentAndFalseOnElement(component, templateEl, iteratorNames, extraVars); // As we walk the array, we'll also walk the DOM (updating/creating as we go).
+
+    let currentEl = templateEl;
+    items.forEach((item, index) => {
+      let iterationScopeVariables = getIterationScopeVariables(iteratorNames, item, index, items, extraVars());
+      let currentKey = generateKeyForIteration(component, templateEl, index, iterationScopeVariables);
+      let nextEl = lookAheadForMatchingKeyedElementAndMoveItIfFound(currentEl.nextElementSibling, currentKey); // If we haven't found a matching key, insert the element at the current position.
+
+      if (!nextEl) {
+        nextEl = addElementInLoopAfterCurrentEl(templateEl, currentEl); // And transition it in if it's not the first page load.
+
+        transitionIn(nextEl, () => {}, () => {}, component, initialUpdate);
+        nextEl.__x_for = iterationScopeVariables;
+        component.initializeElements(nextEl, () => nextEl.__x_for); // Otherwise update the element we found.
+      } else {
+        // Temporarily remove the key indicator to allow the normal "updateElements" to work.
+        delete nextEl.__x_for_key;
+        nextEl.__x_for = iterationScopeVariables;
+        component.updateElements(nextEl, () => nextEl.__x_for);
+      }
+
+      currentEl = nextEl;
+      currentEl.__x_for_key = currentKey;
+    });
+    removeAnyLeftOverElementsFromPreviousUpdate(currentEl, component);
+  } // This was taken from VueJS 2.* core. Thanks Vue!
+
+  function parseForExpression(expression) {
+    let forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;
+    let stripParensRE = /^\(|\)$/g;
+    let forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;
+    let inMatch = String(expression).match(forAliasRE);
+    if (!inMatch) return;
+    let res = {};
+    res.items = inMatch[2].trim();
+    let item = inMatch[1].trim().replace(stripParensRE, '');
+    let iteratorMatch = item.match(forIteratorRE);
+
+    if (iteratorMatch) {
+      res.item = item.replace(forIteratorRE, '').trim();
+      res.index = iteratorMatch[1].trim();
+
+      if (iteratorMatch[2]) {
+        res.collection = iteratorMatch[2].trim();
+      }
+    } else {
+      res.item = item;
+    }
+
+    return res;
+  }
+
+  function getIterationScopeVariables(iteratorNames, item, index, items, extraVars) {
+    // We must create a new object, so each iteration has a new scope
+    let scopeVariables = extraVars ? _objectSpread2({}, extraVars) : {};
+    scopeVariables[iteratorNames.item] = item;
+    if (iteratorNames.index) scopeVariables[iteratorNames.index] = index;
+    if (iteratorNames.collection) scopeVariables[iteratorNames.collection] = items;
+    return scopeVariables;
+  }
+
+  function generateKeyForIteration(component, el, index, iterationScopeVariables) {
+    let bindKeyAttribute = getXAttrs(el, component, 'bind').filter(attr => attr.value === 'key')[0]; // If the dev hasn't specified a key, just return the index of the iteration.
+
+    if (!bindKeyAttribute) return index;
+    return component.evaluateReturnExpression(el, bindKeyAttribute.expression, () => iterationScopeVariables);
+  }
+
+  function evaluateItemsAndReturnEmptyIfXIfIsPresentAndFalseOnElement(component, el, iteratorNames, extraVars) {
+    let ifAttribute = getXAttrs(el, component, 'if')[0];
+
+    if (ifAttribute && !component.evaluateReturnExpression(el, ifAttribute.expression)) {
+      return [];
+    }
+
+    let items = component.evaluateReturnExpression(el, iteratorNames.items, extraVars); // This adds support for the `i in n` syntax.
+
+    if (isNumeric(items) && items >= 0) {
+      items = Array.from(Array(items).keys(), i => i + 1);
+    }
+
+    return items;
+  }
+
+  function addElementInLoopAfterCurrentEl(templateEl, currentEl) {
+    let clone = document.importNode(templateEl.content, true);
+    currentEl.parentElement.insertBefore(clone, currentEl.nextElementSibling);
+    return currentEl.nextElementSibling;
+  }
+
+  function lookAheadForMatchingKeyedElementAndMoveItIfFound(nextEl, currentKey) {
+    if (!nextEl) return; // If we are already past the x-for generated elements, we don't need to look ahead.
+
+    if (nextEl.__x_for_key === undefined) return; // If the the key's DO match, no need to look ahead.
+
+    if (nextEl.__x_for_key === currentKey) return nextEl; // If they don't, we'll look ahead for a match.
+    // If we find it, we'll move it to the current position in the loop.
+
+    let tmpNextEl = nextEl;
+
+    while (tmpNextEl) {
+      if (tmpNextEl.__x_for_key === currentKey) {
+        return tmpNextEl.parentElement.insertBefore(tmpNextEl, nextEl);
+      }
+
+      tmpNextEl = tmpNextEl.nextElementSibling && tmpNextEl.nextElementSibling.__x_for_key !== undefined ? tmpNextEl.nextElementSibling : false;
+    }
+  }
+
+  function removeAnyLeftOverElementsFromPreviousUpdate(currentEl, component) {
+    var nextElementFromOldLoop = currentEl.nextElementSibling && currentEl.nextElementSibling.__x_for_key !== undefined ? currentEl.nextElementSibling : false;
+
+    while (nextElementFromOldLoop) {
+      let nextElementFromOldLoopImmutable = nextElementFromOldLoop;
+      let nextSibling = nextElementFromOldLoop.nextElementSibling;
+      transitionOut(nextElementFromOldLoop, () => {
+        nextElementFromOldLoopImmutable.remove();
+      }, () => {}, component);
+      nextElementFromOldLoop = nextSibling && nextSibling.__x_for_key !== undefined ? nextSibling : false;
+    }
+  }
+
+  function handleAttributeBindingDirective(component, el, attrName, expression, extraVars, attrType, modifiers) {
+    var value = component.evaluateReturnExpression(el, expression, extraVars);
+
+    if (attrName === 'value') {
+      if (Alpine.ignoreFocusedForValueBinding && document.activeElement.isSameNode(el)) return; // If nested model key is undefined, set the default value to empty string.
+
+      if (value === undefined && String(expression).match(/\./)) {
+        value = '';
+      }
+
+      if (el.type === 'radio') {
+        // Set radio value from x-bind:value, if no "value" attribute exists.
+        // If there are any initial state values, radio will have a correct
+        // "checked" value since x-bind:value is processed before x-model.
+        if (el.attributes.value === undefined && attrType === 'bind') {
+          el.value = value;
+        } else if (attrType !== 'bind') {
+          el.checked = checkedAttrLooseCompare(el.value, value);
+        }
+      } else if (el.type === 'checkbox') {
+        // If we are explicitly binding a string to the :value, set the string,
+        // If the value is a boolean, leave it alone, it will be set to "on"
+        // automatically.
+        if (typeof value !== 'boolean' && ![null, undefined].includes(value) && attrType === 'bind') {
+          el.value = String(value);
+        } else if (attrType !== 'bind') {
+          if (Array.isArray(value)) {
+            // I'm purposely not using Array.includes here because it's
+            // strict, and because of Numeric/String mis-casting, I
+            // want the "includes" to be "fuzzy".
+            el.checked = value.some(val => checkedAttrLooseCompare(val, el.value));
+          } else {
+            el.checked = !!value;
+          }
+        }
+      } else if (el.tagName === 'SELECT') {
+        updateSelect(el, value);
+      } else {
+        if (el.value === value) return;
+        el.value = value;
+      }
+    } else if (attrName === 'class') {
+      if (Array.isArray(value)) {
+        const originalClasses = el.__x_original_classes || [];
+        el.setAttribute('class', arrayUnique(originalClasses.concat(value)).join(' '));
+      } else if (typeof value === 'object') {
+        // Sorting the keys / class names by their boolean value will ensure that
+        // anything that evaluates to `false` and needs to remove classes is run first.
+        const keysSortedByBooleanValue = Object.keys(value).sort((a, b) => value[a] - value[b]);
+        keysSortedByBooleanValue.forEach(classNames => {
+          if (value[classNames]) {
+            convertClassStringToArray(classNames).forEach(className => el.classList.add(className));
+          } else {
+            convertClassStringToArray(classNames).forEach(className => el.classList.remove(className));
+          }
+        });
+      } else {
+        const originalClasses = el.__x_original_classes || [];
+        const newClasses = value ? convertClassStringToArray(value) : [];
+        el.setAttribute('class', arrayUnique(originalClasses.concat(newClasses)).join(' '));
+      }
+    } else {
+      attrName = modifiers.includes('camel') ? camelCase(attrName) : attrName; // If an attribute's bound value is null, undefined or false, remove the attribute
+
+      if ([null, undefined, false].includes(value)) {
+        el.removeAttribute(attrName);
+      } else {
+        isBooleanAttr(attrName) ? setIfChanged(el, attrName, attrName) : setIfChanged(el, attrName, value);
+      }
+    }
+  }
+
+  function setIfChanged(el, attrName, value) {
+    if (el.getAttribute(attrName) != value) {
+      el.setAttribute(attrName, value);
+    }
+  }
+
+  function updateSelect(el, value) {
+    const arrayWrappedValue = [].concat(value).map(value => {
+      return value + '';
+    });
+    Array.from(el.options).forEach(option => {
+      option.selected = arrayWrappedValue.includes(option.value);
+    });
+  }
+
+  function handleTextDirective(el, output, expression) {
+    // If nested model key is undefined, set the default value to empty string.
+    if (output === undefined && String(expression).match(/\./)) {
+      output = '';
+    }
+
+    el.textContent = output;
+  }
+
+  function handleHtmlDirective(component, el, expression, extraVars) {
+    el.innerHTML = component.evaluateReturnExpression(el, expression, extraVars);
+  }
+
+  function handleShowDirective(component, el, value, modifiers, initialUpdate = false) {
+    const hide = () => {
+      el.style.display = 'none';
+      el.__x_is_shown = false;
+    };
+
+    const show = () => {
+      if (el.style.length === 1 && el.style.display === 'none') {
+        el.removeAttribute('style');
+      } else {
+        el.style.removeProperty('display');
+      }
+
+      el.__x_is_shown = true;
+    };
+
+    if (initialUpdate === true) {
+      if (value) {
+        show();
+      } else {
+        hide();
+      }
+
+      return;
+    }
+
+    const handle = (resolve, reject) => {
+      if (value) {
+        if (el.style.display === 'none' || el.__x_transition) {
+          transitionIn(el, () => {
+            show();
+          }, reject, component);
+        }
+
+        resolve(() => {});
+      } else {
+        if (el.style.display !== 'none') {
+          transitionOut(el, () => {
+            resolve(() => {
+              hide();
+            });
+          }, reject, component);
+        } else {
+          resolve(() => {});
+        }
+      }
+    }; // The working of x-show is a bit complex because we need to
+    // wait for any child transitions to finish before hiding
+    // some element. Also, this has to be done recursively.
+    // If x-show.immediate, foregoe the waiting.
+
+
+    if (modifiers.includes('immediate')) {
+      handle(finish => finish(), () => {});
+      return;
+    } // x-show is encountered during a DOM tree walk. If an element
+    // we encounter is NOT a child of another x-show element we
+    // can execute the previous x-show stack (if one exists).
+
+
+    if (component.showDirectiveLastElement && !component.showDirectiveLastElement.contains(el)) {
+      component.executeAndClearRemainingShowDirectiveStack();
+    }
+
+    component.showDirectiveStack.push(handle);
+    component.showDirectiveLastElement = el;
+  }
+
+  function handleIfDirective(component, el, expressionResult, initialUpdate, extraVars) {
+    warnIfMalformedTemplate(el, 'x-if');
+    const elementHasAlreadyBeenAdded = el.nextElementSibling && el.nextElementSibling.__x_inserted_me === true;
+
+    if (expressionResult && (!elementHasAlreadyBeenAdded || el.__x_transition)) {
+      const clone = document.importNode(el.content, true);
+      el.parentElement.insertBefore(clone, el.nextElementSibling);
+      transitionIn(el.nextElementSibling, () => {}, () => {}, component, initialUpdate);
+      component.initializeElements(el.nextElementSibling, extraVars);
+      el.nextElementSibling.__x_inserted_me = true;
+    } else if (!expressionResult && elementHasAlreadyBeenAdded) {
+      transitionOut(el.nextElementSibling, () => {
+        el.nextElementSibling.remove();
+      }, () => {}, component, initialUpdate);
+    }
+  }
+
+  function registerListener(component, el, event, modifiers, expression, extraVars = {}) {
+    const options = {
+      passive: modifiers.includes('passive')
+    };
+
+    if (modifiers.includes('camel')) {
+      event = camelCase(event);
+    }
+
+    const node_add_count = el.__x_node_add_count;
+    let handler, listenerTarget;
+
+    if (modifiers.includes('away')) {
+      listenerTarget = document;
+
+      handler = e => {
+        // Don't do anything if the click came from the element or within it.
+        if (el.contains(e.target)) return; // Don't do anything if this element isn't currently visible.
+
+        if (el.offsetWidth < 1 && el.offsetHeight < 1) return; // Now that we are sure the element is visible, AND the click
+        // is from outside it, let's run the expression.
+
+        runListenerHandler(component, expression, e, extraVars);
+
+        if (modifiers.includes('once')) {
+          document.removeEventListener(event, handler, options);
+        }
+      };
+    } else {
+      listenerTarget = modifiers.includes('window') ? window : modifiers.includes('document') ? document : el;
+
+      handler = e => {
+        // Remove this global event handler if the element that declared it
+        // has been removed. It's now stale.
+        if (listenerTarget === window || listenerTarget === document) {
+          if (!document.body.contains(el)) {
+            listenerTarget.removeEventListener(event, handler, options);
+            return;
+          }
+        }
+
+        if (el.__x_node_add_count !== node_add_count) {
+          listenerTarget.removeEventListener(event, handler, options);
+          return;
+        }
+
+        if (isKeyEvent(event)) {
+          if (isListeningForASpecificKeyThatHasntBeenPressed(e, modifiers)) {
+            return;
+          }
+        }
+
+        if (modifiers.includes('prevent')) e.preventDefault();
+        if (modifiers.includes('stop')) e.stopPropagation(); // If the .self modifier isn't present, or if it is present and
+        // the target element matches the element we are registering the
+        // event on, run the handler
+
+        if (!modifiers.includes('self') || e.target === el) {
+          const returnValue = runListenerHandler(component, expression, e, extraVars);
+          returnValue.then(value => {
+            if (value === false) {
+              e.preventDefault();
+            } else {
+              if (modifiers.includes('once')) {
+                listenerTarget.removeEventListener(event, handler, options);
+              }
+            }
+          });
+        }
+      };
+    }
+
+    if (modifiers.includes('debounce')) {
+      let nextModifier = modifiers[modifiers.indexOf('debounce') + 1] || 'invalid-wait';
+      let wait = isNumeric(nextModifier.split('ms')[0]) ? Number(nextModifier.split('ms')[0]) : 250;
+      handler = debounce(handler, wait);
+    }
+
+    listenerTarget.addEventListener(event, handler, options);
+  }
+
+  function runListenerHandler(component, expression, e, extraVars) {
+    return component.evaluateCommandExpression(e.target, expression, () => {
+      return _objectSpread2(_objectSpread2({}, extraVars()), {}, {
+        '$event': e
+      });
+    });
+  }
+
+  function isKeyEvent(event) {
+    return ['keydown', 'keyup'].includes(event);
+  }
+
+  function isListeningForASpecificKeyThatHasntBeenPressed(e, modifiers) {
+    let keyModifiers = modifiers.filter(i => {
+      return !['window', 'document', 'prevent', 'stop'].includes(i);
+    });
+
+    if (keyModifiers.includes('debounce')) {
+      let debounceIndex = keyModifiers.indexOf('debounce');
+      keyModifiers.splice(debounceIndex, isNumeric((keyModifiers[debounceIndex + 1] || 'invalid-wait').split('ms')[0]) ? 2 : 1);
+    } // If no modifier is specified, we'll call it a press.
+
+
+    if (keyModifiers.length === 0) return false; // If one is passed, AND it matches the key pressed, we'll call it a press.
+
+    if (keyModifiers.length === 1 && keyModifiers[0] === keyToModifier(e.key)) return false; // The user is listening for key combinations.
+
+    const systemKeyModifiers = ['ctrl', 'shift', 'alt', 'meta', 'cmd', 'super'];
+    const selectedSystemKeyModifiers = systemKeyModifiers.filter(modifier => keyModifiers.includes(modifier));
+    keyModifiers = keyModifiers.filter(i => !selectedSystemKeyModifiers.includes(i));
+
+    if (selectedSystemKeyModifiers.length > 0) {
+      const activelyPressedKeyModifiers = selectedSystemKeyModifiers.filter(modifier => {
+        // Alias "cmd" and "super" to "meta"
+        if (modifier === 'cmd' || modifier === 'super') modifier = 'meta';
+        return e[`${modifier}Key`];
+      }); // If all the modifiers selected are pressed, ...
+
+      if (activelyPressedKeyModifiers.length === selectedSystemKeyModifiers.length) {
+        // AND the remaining key is pressed as well. It's a press.
+        if (keyModifiers[0] === keyToModifier(e.key)) return false;
+      }
+    } // We'll call it NOT a valid keypress.
+
+
+    return true;
+  }
+
+  function keyToModifier(key) {
+    switch (key) {
+      case '/':
+        return 'slash';
+
+      case ' ':
+      case 'Spacebar':
+        return 'space';
+
+      default:
+        return key && kebabCase(key);
+    }
+  }
+
+  function registerModelListener(component, el, modifiers, expression, extraVars) {
+    // If the element we are binding to is a select, a radio, or checkbox
+    // we'll listen for the change event instead of the "input" event.
+    var event = el.tagName.toLowerCase() === 'select' || ['checkbox', 'radio'].includes(el.type) || modifiers.includes('lazy') ? 'change' : 'input';
+    const listenerExpression = `${expression} = rightSideOfExpression($event, ${expression})`;
+    registerListener(component, el, event, modifiers, listenerExpression, () => {
+      return _objectSpread2(_objectSpread2({}, extraVars()), {}, {
+        rightSideOfExpression: generateModelAssignmentFunction(el, modifiers, expression)
+      });
+    });
+  }
+
+  function generateModelAssignmentFunction(el, modifiers, expression) {
+    if (el.type === 'radio') {
+      // Radio buttons only work properly when they share a name attribute.
+      // People might assume we take care of that for them, because
+      // they already set a shared "x-model" attribute.
+      if (!el.hasAttribute('name')) el.setAttribute('name', expression);
+    }
+
+    return (event, currentValue) => {
+      // Check for event.detail due to an issue where IE11 handles other events as a CustomEvent.
+      if (event instanceof CustomEvent && event.detail) {
+        return event.detail;
+      } else if (el.type === 'checkbox') {
+        // If the data we are binding to is an array, toggle its value inside the array.
+        if (Array.isArray(currentValue)) {
+          const newValue = modifiers.includes('number') ? safeParseNumber(event.target.value) : event.target.value;
+          return event.target.checked ? currentValue.concat([newValue]) : currentValue.filter(el => !checkedAttrLooseCompare(el, newValue));
+        } else {
+          return event.target.checked;
+        }
+      } else if (el.tagName.toLowerCase() === 'select' && el.multiple) {
+        return modifiers.includes('number') ? Array.from(event.target.selectedOptions).map(option => {
+          const rawValue = option.value || option.text;
+          return safeParseNumber(rawValue);
+        }) : Array.from(event.target.selectedOptions).map(option => {
+          return option.value || option.text;
+        });
+      } else {
+        const rawValue = event.target.value;
+        return modifiers.includes('number') ? safeParseNumber(rawValue) : modifiers.includes('trim') ? rawValue.trim() : rawValue;
+      }
+    };
+  }
+
+  function safeParseNumber(rawValue) {
+    const number = rawValue ? parseFloat(rawValue) : null;
+    return isNumeric(number) ? number : rawValue;
+  }
+
+  /**
+   * Copyright (C) 2017 salesforce.com, inc.
+   */
+  const { isArray } = Array;
+  const { getPrototypeOf, create: ObjectCreate, defineProperty: ObjectDefineProperty, defineProperties: ObjectDefineProperties, isExtensible, getOwnPropertyDescriptor, getOwnPropertyNames, getOwnPropertySymbols, preventExtensions, hasOwnProperty, } = Object;
+  const { push: ArrayPush, concat: ArrayConcat, map: ArrayMap, } = Array.prototype;
+  function isUndefined(obj) {
+      return obj === undefined;
+  }
+  function isFunction(obj) {
+      return typeof obj === 'function';
+  }
+  function isObject(obj) {
+      return typeof obj === 'object';
+  }
+  const proxyToValueMap = new WeakMap();
+  function registerProxy(proxy, value) {
+      proxyToValueMap.set(proxy, value);
+  }
+  const unwrap$1 = (replicaOrAny) => proxyToValueMap.get(replicaOrAny) || replicaOrAny;
+
+  function wrapValue(membrane, value) {
+      return membrane.valueIsObservable(value) ? membrane.getProxy(value) : value;
+  }
+  /**
+   * Unwrap property descriptors will set value on original descriptor
+   * We only need to unwrap if value is specified
+   * @param descriptor external descrpitor provided to define new property on original value
+   */
+  function unwrapDescriptor(descriptor) {
+      if (hasOwnProperty.call(descriptor, 'value')) {
+          descriptor.value = unwrap$1(descriptor.value);
+      }
+      return descriptor;
+  }
+  function lockShadowTarget(membrane, shadowTarget, originalTarget) {
+      const targetKeys = ArrayConcat.call(getOwnPropertyNames(originalTarget), getOwnPropertySymbols(originalTarget));
+      targetKeys.forEach((key) => {
+          let descriptor = getOwnPropertyDescriptor(originalTarget, key);
+          // We do not need to wrap the descriptor if configurable
+          // Because we can deal with wrapping it when user goes through
+          // Get own property descriptor. There is also a chance that this descriptor
+          // could change sometime in the future, so we can defer wrapping
+          // until we need to
+          if (!descriptor.configurable) {
+              descriptor = wrapDescriptor(membrane, descriptor, wrapValue);
+          }
+          ObjectDefineProperty(shadowTarget, key, descriptor);
+      });
+      preventExtensions(shadowTarget);
+  }
+  class ReactiveProxyHandler {
+      constructor(membrane, value) {
+          this.originalTarget = value;
+          this.membrane = membrane;
+      }
+      get(shadowTarget, key) {
+          const { originalTarget, membrane } = this;
+          const value = originalTarget[key];
+          const { valueObserved } = membrane;
+          valueObserved(originalTarget, key);
+          return membrane.getProxy(value);
+      }
+      set(shadowTarget, key, value) {
+          const { originalTarget, membrane: { valueMutated } } = this;
+          const oldValue = originalTarget[key];
+          if (oldValue !== value) {
+              originalTarget[key] = value;
+              valueMutated(originalTarget, key);
+          }
+          else if (key === 'length' && isArray(originalTarget)) {
+              // fix for issue #236: push will add the new index, and by the time length
+              // is updated, the internal length is already equal to the new length value
+              // therefore, the oldValue is equal to the value. This is the forking logic
+              // to support this use case.
+              valueMutated(originalTarget, key);
+          }
+          return true;
+      }
+      deleteProperty(shadowTarget, key) {
+          const { originalTarget, membrane: { valueMutated } } = this;
+          delete originalTarget[key];
+          valueMutated(originalTarget, key);
+          return true;
+      }
+      apply(shadowTarget, thisArg, argArray) {
+          /* No op */
+      }
+      construct(target, argArray, newTarget) {
+          /* No op */
+      }
+      has(shadowTarget, key) {
+          const { originalTarget, membrane: { valueObserved } } = this;
+          valueObserved(originalTarget, key);
+          return key in originalTarget;
+      }
+      ownKeys(shadowTarget) {
+          const { originalTarget } = this;
+          return ArrayConcat.call(getOwnPropertyNames(originalTarget), getOwnPropertySymbols(originalTarget));
+      }
+      isExtensible(shadowTarget) {
+          const shadowIsExtensible = isExtensible(shadowTarget);
+          if (!shadowIsExtensible) {
+              return shadowIsExtensible;
+          }
+          const { originalTarget, membrane } = this;
+          const targetIsExtensible = isExtensible(originalTarget);
+          if (!targetIsExtensible) {
+              lockShadowTarget(membrane, shadowTarget, originalTarget);
+          }
+          return targetIsExtensible;
+      }
+      setPrototypeOf(shadowTarget, prototype) {
+      }
+      getPrototypeOf(shadowTarget) {
+          const { originalTarget } = this;
+          return getPrototypeOf(originalTarget);
+      }
+      getOwnPropertyDescriptor(shadowTarget, key) {
+          const { originalTarget, membrane } = this;
+          const { valueObserved } = this.membrane;
+          // keys looked up via hasOwnProperty need to be reactive
+          valueObserved(originalTarget, key);
+          let desc = getOwnPropertyDescriptor(originalTarget, key);
+          if (isUndefined(desc)) {
+              return desc;
+          }
+          const shadowDescriptor = getOwnPropertyDescriptor(shadowTarget, key);
+          if (!isUndefined(shadowDescriptor)) {
+              return shadowDescriptor;
+          }
+          // Note: by accessing the descriptor, the key is marked as observed
+          // but access to the value, setter or getter (if available) cannot observe
+          // mutations, just like regular methods, in which case we just do nothing.
+          desc = wrapDescriptor(membrane, desc, wrapValue);
+          if (!desc.configurable) {
+              // If descriptor from original target is not configurable,
+              // We must copy the wrapped descriptor over to the shadow target.
+              // Otherwise, proxy will throw an invariant error.
+              // This is our last chance to lock the value.
+              // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/getOwnPropertyDescriptor#Invariants
+              ObjectDefineProperty(shadowTarget, key, desc);
+          }
+          return desc;
+      }
+      preventExtensions(shadowTarget) {
+          const { originalTarget, membrane } = this;
+          lockShadowTarget(membrane, shadowTarget, originalTarget);
+          preventExtensions(originalTarget);
+          return true;
+      }
+      defineProperty(shadowTarget, key, descriptor) {
+          const { originalTarget, membrane } = this;
+          const { valueMutated } = membrane;
+          const { configurable } = descriptor;
+          // We have to check for value in descriptor
+          // because Object.freeze(proxy) calls this method
+          // with only { configurable: false, writeable: false }
+          // Additionally, method will only be called with writeable:false
+          // if the descriptor has a value, as opposed to getter/setter
+          // So we can just check if writable is present and then see if
+          // value is present. This eliminates getter and setter descriptors
+          if (hasOwnProperty.call(descriptor, 'writable') && !hasOwnProperty.call(descriptor, 'value')) {
+              const originalDescriptor = getOwnPropertyDescriptor(originalTarget, key);
+              descriptor.value = originalDescriptor.value;
+          }
+          ObjectDefineProperty(originalTarget, key, unwrapDescriptor(descriptor));
+          if (configurable === false) {
+              ObjectDefineProperty(shadowTarget, key, wrapDescriptor(membrane, descriptor, wrapValue));
+          }
+          valueMutated(originalTarget, key);
+          return true;
+      }
+  }
+
+  function wrapReadOnlyValue(membrane, value) {
+      return membrane.valueIsObservable(value) ? membrane.getReadOnlyProxy(value) : value;
+  }
+  class ReadOnlyHandler {
+      constructor(membrane, value) {
+          this.originalTarget = value;
+          this.membrane = membrane;
+      }
+      get(shadowTarget, key) {
+          const { membrane, originalTarget } = this;
+          const value = originalTarget[key];
+          const { valueObserved } = membrane;
+          valueObserved(originalTarget, key);
+          return membrane.getReadOnlyProxy(value);
+      }
+      set(shadowTarget, key, value) {
+          return false;
+      }
+      deleteProperty(shadowTarget, key) {
+          return false;
+      }
+      apply(shadowTarget, thisArg, argArray) {
+          /* No op */
+      }
+      construct(target, argArray, newTarget) {
+          /* No op */
+      }
+      has(shadowTarget, key) {
+          const { originalTarget, membrane: { valueObserved } } = this;
+          valueObserved(originalTarget, key);
+          return key in originalTarget;
+      }
+      ownKeys(shadowTarget) {
+          const { originalTarget } = this;
+          return ArrayConcat.call(getOwnPropertyNames(originalTarget), getOwnPropertySymbols(originalTarget));
+      }
+      setPrototypeOf(shadowTarget, prototype) {
+      }
+      getOwnPropertyDescriptor(shadowTarget, key) {
+          const { originalTarget, membrane } = this;
+          const { valueObserved } = membrane;
+          // keys looked up via hasOwnProperty need to be reactive
+          valueObserved(originalTarget, key);
+          let desc = getOwnPropertyDescriptor(originalTarget, key);
+          if (isUndefined(desc)) {
+              return desc;
+          }
+          const shadowDescriptor = getOwnPropertyDescriptor(shadowTarget, key);
+          if (!isUndefined(shadowDescriptor)) {
+              return shadowDescriptor;
+          }
+          // Note: by accessing the descriptor, the key is marked as observed
+          // but access to the value or getter (if available) cannot be observed,
+          // just like regular methods, in which case we just do nothing.
+          desc = wrapDescriptor(membrane, desc, wrapReadOnlyValue);
+          if (hasOwnProperty.call(desc, 'set')) {
+              desc.set = undefined; // readOnly membrane does not allow setters
+          }
+          if (!desc.configurable) {
+              // If descriptor from original target is not configurable,
+              // We must copy the wrapped descriptor over to the shadow target.
+              // Otherwise, proxy will throw an invariant error.
+              // This is our last chance to lock the value.
+              // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/getOwnPropertyDescriptor#Invariants
+              ObjectDefineProperty(shadowTarget, key, desc);
+          }
+          return desc;
+      }
+      preventExtensions(shadowTarget) {
+          return false;
+      }
+      defineProperty(shadowTarget, key, descriptor) {
+          return false;
+      }
+  }
+  function createShadowTarget(value) {
+      let shadowTarget = undefined;
+      if (isArray(value)) {
+          shadowTarget = [];
+      }
+      else if (isObject(value)) {
+          shadowTarget = {};
+      }
+      return shadowTarget;
+  }
+  const ObjectDotPrototype = Object.prototype;
+  function defaultValueIsObservable(value) {
+      // intentionally checking for null
+      if (value === null) {
+          return false;
+      }
+      // treat all non-object types, including undefined, as non-observable values
+      if (typeof value !== 'object') {
+          return false;
+      }
+      if (isArray(value)) {
+          return true;
+      }
+      const proto = getPrototypeOf(value);
+      return (proto === ObjectDotPrototype || proto === null || getPrototypeOf(proto) === null);
+  }
+  const defaultValueObserved = (obj, key) => {
+      /* do nothing */
+  };
+  const defaultValueMutated = (obj, key) => {
+      /* do nothing */
+  };
+  const defaultValueDistortion = (value) => value;
+  function wrapDescriptor(membrane, descriptor, getValue) {
+      const { set, get } = descriptor;
+      if (hasOwnProperty.call(descriptor, 'value')) {
+          descriptor.value = getValue(membrane, descriptor.value);
+      }
+      else {
+          if (!isUndefined(get)) {
+              descriptor.get = function () {
+                  // invoking the original getter with the original target
+                  return getValue(membrane, get.call(unwrap$1(this)));
+              };
+          }
+          if (!isUndefined(set)) {
+              descriptor.set = function (value) {
+                  // At this point we don't have a clear indication of whether
+                  // or not a valid mutation will occur, we don't have the key,
+                  // and we are not sure why and how they are invoking this setter.
+                  // Nevertheless we preserve the original semantics by invoking the
+                  // original setter with the original target and the unwrapped value
+                  set.call(unwrap$1(this), membrane.unwrapProxy(value));
+              };
+          }
+      }
+      return descriptor;
+  }
+  class ReactiveMembrane {
+      constructor(options) {
+          this.valueDistortion = defaultValueDistortion;
+          this.valueMutated = defaultValueMutated;
+          this.valueObserved = defaultValueObserved;
+          this.valueIsObservable = defaultValueIsObservable;
+          this.objectGraph = new WeakMap();
+          if (!isUndefined(options)) {
+              const { valueDistortion, valueMutated, valueObserved, valueIsObservable } = options;
+              this.valueDistortion = isFunction(valueDistortion) ? valueDistortion : defaultValueDistortion;
+              this.valueMutated = isFunction(valueMutated) ? valueMutated : defaultValueMutated;
+              this.valueObserved = isFunction(valueObserved) ? valueObserved : defaultValueObserved;
+              this.valueIsObservable = isFunction(valueIsObservable) ? valueIsObservable : defaultValueIsObservable;
+          }
+      }
+      getProxy(value) {
+          const unwrappedValue = unwrap$1(value);
+          const distorted = this.valueDistortion(unwrappedValue);
+          if (this.valueIsObservable(distorted)) {
+              const o = this.getReactiveState(unwrappedValue, distorted);
+              // when trying to extract the writable version of a readonly
+              // we return the readonly.
+              return o.readOnly === value ? value : o.reactive;
+          }
+          return distorted;
+      }
+      getReadOnlyProxy(value) {
+          value = unwrap$1(value);
+          const distorted = this.valueDistortion(value);
+          if (this.valueIsObservable(distorted)) {
+              return this.getReactiveState(value, distorted).readOnly;
+          }
+          return distorted;
+      }
+      unwrapProxy(p) {
+          return unwrap$1(p);
+      }
+      getReactiveState(value, distortedValue) {
+          const { objectGraph, } = this;
+          let reactiveState = objectGraph.get(distortedValue);
+          if (reactiveState) {
+              return reactiveState;
+          }
+          const membrane = this;
+          reactiveState = {
+              get reactive() {
+                  const reactiveHandler = new ReactiveProxyHandler(membrane, distortedValue);
+                  // caching the reactive proxy after the first time it is accessed
+                  const proxy = new Proxy(createShadowTarget(distortedValue), reactiveHandler);
+                  registerProxy(proxy, value);
+                  ObjectDefineProperty(this, 'reactive', { value: proxy });
+                  return proxy;
+              },
+              get readOnly() {
+                  const readOnlyHandler = new ReadOnlyHandler(membrane, distortedValue);
+                  // caching the readOnly proxy after the first time it is accessed
+                  const proxy = new Proxy(createShadowTarget(distortedValue), readOnlyHandler);
+                  registerProxy(proxy, value);
+                  ObjectDefineProperty(this, 'readOnly', { value: proxy });
+                  return proxy;
+              }
+          };
+          objectGraph.set(distortedValue, reactiveState);
+          return reactiveState;
+      }
+  }
+  /** version: 0.26.0 */
+
+  function wrap(data, mutationCallback) {
+
+    let membrane = new ReactiveMembrane({
+      valueMutated(target, key) {
+        mutationCallback(target, key);
+      }
+
+    });
+    return {
+      data: membrane.getProxy(data),
+      membrane: membrane
+    };
+  }
+  function unwrap(membrane, observable) {
+    let unwrappedData = membrane.unwrapProxy(observable);
+    let copy = {};
+    Object.keys(unwrappedData).forEach(key => {
+      if (['$el', '$refs', '$nextTick', '$watch'].includes(key)) return;
+      copy[key] = unwrappedData[key];
+    });
+    return copy;
+  }
+
+  class Component {
+    constructor(el, componentForClone = null) {
+      this.$el = el;
+      const dataAttr = this.$el.getAttribute('x-data');
+      const dataExpression = dataAttr === '' ? '{}' : dataAttr;
+      let dataExtras = {
+        $el: this.$el
+      };
+      let canonicalComponentElementReference = componentForClone ? componentForClone.$el : this.$el;
+      Object.entries(Alpine.magicProperties).forEach(([name, callback]) => {
+        Object.defineProperty(dataExtras, `$${name}`, {
+          get: function get() {
+            return callback(canonicalComponentElementReference);
+          }
+        });
+      });
+      this.unobservedData = componentForClone ? componentForClone.getUnobservedData() : saferEval(el, dataExpression, dataExtras);
+      // Construct a Proxy-based observable. This will be used to handle reactivity.
+
+      let {
+        membrane,
+        data
+      } = this.wrapDataInObservable(this.unobservedData);
+      this.$data = data;
+      this.membrane = membrane; // After making user-supplied data methods reactive, we can now add
+      // our magic properties to the original data for access.
+
+      this.unobservedData.$el = this.$el;
+      this.unobservedData.$refs = this.getRefsProxy();
+      this.nextTickStack = [];
+
+      this.unobservedData.$nextTick = callback => {
+        this.nextTickStack.push(callback);
+      };
+
+      this.watchers = {};
+
+      this.unobservedData.$watch = (property, callback) => {
+        if (!this.watchers[property]) this.watchers[property] = [];
+        this.watchers[property].push(callback);
+      };
+      /* MODERN-ONLY:START */
+      // We remove this piece of code from the legacy build.
+      // In IE11, we have already defined our helpers at this point.
+      // Register custom magic properties.
+
+
+      Object.entries(Alpine.magicProperties).forEach(([name, callback]) => {
+        Object.defineProperty(this.unobservedData, `$${name}`, {
+          get: function get() {
+            return callback(canonicalComponentElementReference, this.$el);
+          }
+        });
+      });
+      /* MODERN-ONLY:END */
+
+      this.showDirectiveStack = [];
+      this.showDirectiveLastElement;
+      componentForClone || Alpine.onBeforeComponentInitializeds.forEach(callback => callback(this));
+      const initExpression = this.$el.getAttribute('x-init');
+      var initReturnedCallback; // If x-init is present AND we aren't cloning (skip x-init on clone)
+
+      if (initExpression && !componentForClone) {
+        // We want to allow data manipulation, but not trigger DOM updates just yet.
+        // We haven't even initialized the elements with their Alpine bindings. I mean c'mon.
+        this.pauseReactivity = true;
+        initReturnedCallback = this.evaluateReturnExpression(this.$el, initExpression);
+        this.pauseReactivity = false;
+      } // Register all our listeners and set all our attribute bindings.
+      // If we're cloning a component, the third parameter ensures no duplicate
+      // event listeners are registered (the mutation observer will take care of them)
+
+
+      this.initializeElements(this.$el, () => {}, componentForClone); // Use mutation observer to detect new elements being added within this component at run-time.
+      // Alpine's just so darn flexible amirite?
+
+      this.listenForNewElementsToInitialize();
+
+      if (typeof initReturnedCallback === 'function') {
+        // Run the callback returned from the "x-init" hook to allow the user to do stuff after
+        // Alpine's got it's grubby little paws all over everything.
+        initReturnedCallback.call(this.$data);
+      }
+
+      componentForClone || setTimeout(() => {
+        Alpine.onComponentInitializeds.forEach(callback => callback(this));
+      }, 0);
+    }
+
+    getUnobservedData() {
+      return unwrap(this.membrane, this.$data);
+    }
+
+    wrapDataInObservable(data) {
+      var self = this;
+      let updateDom = debounce(function () {
+        self.updateElements(self.$el);
+      }, 0);
+      return wrap(data, (target, key) => {
+        if (self.watchers[key]) {
+          // If there's a watcher for this specific key, run it.
+          self.watchers[key].forEach(callback => callback(target[key]));
+        } else if (Array.isArray(target)) {
+          // Arrays are special cases, if any of the items change, we consider the array as mutated.
+          Object.keys(self.watchers).forEach(fullDotNotationKey => {
+            let dotNotationParts = fullDotNotationKey.split('.'); // Ignore length mutations since they would result in duplicate calls.
+            // For example, when calling push, we would get a mutation for the item's key
+            // and a second mutation for the length property.
+
+            if (key === 'length') return;
+            dotNotationParts.reduce((comparisonData, part) => {
+              if (Object.is(target, comparisonData[part])) {
+                self.watchers[fullDotNotationKey].forEach(callback => callback(target));
+              }
+
+              return comparisonData[part];
+            }, self.unobservedData);
+          });
+        } else {
+          // Let's walk through the watchers with "dot-notation" (foo.bar) and see
+          // if this mutation fits any of them.
+          Object.keys(self.watchers).filter(i => i.includes('.')).forEach(fullDotNotationKey => {
+            let dotNotationParts = fullDotNotationKey.split('.'); // If this dot-notation watcher's last "part" doesn't match the current
+            // key, then skip it early for performance reasons.
+
+            if (key !== dotNotationParts[dotNotationParts.length - 1]) return; // Now, walk through the dot-notation "parts" recursively to find
+            // a match, and call the watcher if one's found.
+
+            dotNotationParts.reduce((comparisonData, part) => {
+              if (Object.is(target, comparisonData)) {
+                // Run the watchers.
+                self.watchers[fullDotNotationKey].forEach(callback => callback(target[key]));
+              }
+
+              return comparisonData[part];
+            }, self.unobservedData);
+          });
+        } // Don't react to data changes for cases like the `x-created` hook.
+
+
+        if (self.pauseReactivity) return;
+        updateDom();
+      });
+    }
+
+    walkAndSkipNestedComponents(el, callback, initializeComponentCallback = () => {}) {
+      walk(el, el => {
+        // We've hit a component.
+        if (el.hasAttribute('x-data')) {
+          // If it's not the current one.
+          if (!el.isSameNode(this.$el)) {
+            // Initialize it if it's not.
+            if (!el.__x) initializeComponentCallback(el); // Now we'll let that sub-component deal with itself.
+
+            return false;
+          }
+        }
+
+        return callback(el);
+      });
+    }
+
+    initializeElements(rootEl, extraVars = () => {}, componentForClone = false) {
+      this.walkAndSkipNestedComponents(rootEl, el => {
+        // Don't touch spawns from for loop
+        if (el.__x_for_key !== undefined) return false; // Don't touch spawns from if directives
+
+        if (el.__x_inserted_me !== undefined) return false;
+        this.initializeElement(el, extraVars, componentForClone ? false : true);
+      }, el => {
+        if (!componentForClone) el.__x = new Component(el);
+      });
+      this.executeAndClearRemainingShowDirectiveStack();
+      this.executeAndClearNextTickStack(rootEl);
+    }
+
+    initializeElement(el, extraVars, shouldRegisterListeners = true) {
+      // To support class attribute merging, we have to know what the element's
+      // original class attribute looked like for reference.
+      if (el.hasAttribute('class') && getXAttrs(el, this).length > 0) {
+        el.__x_original_classes = convertClassStringToArray(el.getAttribute('class'));
+      }
+
+      shouldRegisterListeners && this.registerListeners(el, extraVars);
+      this.resolveBoundAttributes(el, true, extraVars);
+    }
+
+    updateElements(rootEl, extraVars = () => {}) {
+      this.walkAndSkipNestedComponents(rootEl, el => {
+        // Don't touch spawns from for loop (and check if the root is actually a for loop in a parent, don't skip it.)
+        if (el.__x_for_key !== undefined && !el.isSameNode(this.$el)) return false;
+        this.updateElement(el, extraVars);
+      }, el => {
+        el.__x = new Component(el);
+      });
+      this.executeAndClearRemainingShowDirectiveStack();
+      this.executeAndClearNextTickStack(rootEl);
+    }
+
+    executeAndClearNextTickStack(el) {
+      // Skip spawns from alpine directives
+      if (el === this.$el && this.nextTickStack.length > 0) {
+        // We run the tick stack after the next frame to allow any
+        // running transitions to pass the initial show stage.
+        requestAnimationFrame(() => {
+          while (this.nextTickStack.length > 0) {
+            this.nextTickStack.shift()();
+          }
+        });
+      }
+    }
+
+    executeAndClearRemainingShowDirectiveStack() {
+      // The goal here is to start all the x-show transitions
+      // and build a nested promise chain so that elements
+      // only hide when the children are finished hiding.
+      this.showDirectiveStack.reverse().map(handler => {
+        return new Promise((resolve, reject) => {
+          handler(resolve, reject);
+        });
+      }).reduce((promiseChain, promise) => {
+        return promiseChain.then(() => {
+          return promise.then(finishElement => {
+            finishElement();
+          });
+        });
+      }, Promise.resolve(() => {})).catch(e => {
+        if (e !== TRANSITION_CANCELLED) throw e;
+      }); // We've processed the handler stack. let's clear it.
+
+      this.showDirectiveStack = [];
+      this.showDirectiveLastElement = undefined;
+    }
+
+    updateElement(el, extraVars) {
+      this.resolveBoundAttributes(el, false, extraVars);
+    }
+
+    registerListeners(el, extraVars) {
+      getXAttrs(el, this).forEach(({
+        type,
+        value,
+        modifiers,
+        expression
+      }) => {
+        switch (type) {
+          case 'on':
+            registerListener(this, el, value, modifiers, expression, extraVars);
+            break;
+
+          case 'model':
+            registerModelListener(this, el, modifiers, expression, extraVars);
+            break;
+        }
+      });
+    }
+
+    resolveBoundAttributes(el, initialUpdate = false, extraVars) {
+      let attrs = getXAttrs(el, this);
+      attrs.forEach(({
+        type,
+        value,
+        modifiers,
+        expression
+      }) => {
+        switch (type) {
+          case 'model':
+            handleAttributeBindingDirective(this, el, 'value', expression, extraVars, type, modifiers);
+            break;
+
+          case 'bind':
+            // The :key binding on an x-for is special, ignore it.
+            if (el.tagName.toLowerCase() === 'template' && value === 'key') return;
+            handleAttributeBindingDirective(this, el, value, expression, extraVars, type, modifiers);
+            break;
+
+          case 'text':
+            var output = this.evaluateReturnExpression(el, expression, extraVars);
+            handleTextDirective(el, output, expression);
+            break;
+
+          case 'html':
+            handleHtmlDirective(this, el, expression, extraVars);
+            break;
+
+          case 'show':
+            var output = this.evaluateReturnExpression(el, expression, extraVars);
+            handleShowDirective(this, el, output, modifiers, initialUpdate);
+            break;
+
+          case 'if':
+            // If this element also has x-for on it, don't process x-if.
+            // We will let the "x-for" directive handle the "if"ing.
+            if (attrs.some(i => i.type === 'for')) return;
+            var output = this.evaluateReturnExpression(el, expression, extraVars);
+            handleIfDirective(this, el, output, initialUpdate, extraVars);
+            break;
+
+          case 'for':
+            handleForDirective(this, el, expression, initialUpdate, extraVars);
+            break;
+
+          case 'cloak':
+            el.removeAttribute('x-cloak');
+            break;
+        }
+      });
+    }
+
+    evaluateReturnExpression(el, expression, extraVars = () => {}) {
+      return saferEval(el, expression, this.$data, _objectSpread2(_objectSpread2({}, extraVars()), {}, {
+        $dispatch: this.getDispatchFunction(el)
+      }));
+    }
+
+    evaluateCommandExpression(el, expression, extraVars = () => {}) {
+      return saferEvalNoReturn(el, expression, this.$data, _objectSpread2(_objectSpread2({}, extraVars()), {}, {
+        $dispatch: this.getDispatchFunction(el)
+      }));
+    }
+
+    getDispatchFunction(el) {
+      return (event, detail = {}) => {
+        el.dispatchEvent(new CustomEvent(event, {
+          detail,
+          bubbles: true
+        }));
+      };
+    }
+
+    listenForNewElementsToInitialize() {
+      const targetNode = this.$el;
+      const observerOptions = {
+        childList: true,
+        attributes: true,
+        subtree: true
+      };
+      const observer = new MutationObserver(mutations => {
+        for (let i = 0; i < mutations.length; i++) {
+          // Filter out mutations triggered from child components.
+          const closestParentComponent = mutations[i].target.closest('[x-data]');
+          if (!(closestParentComponent && closestParentComponent.isSameNode(this.$el))) continue;
+
+          if (mutations[i].type === 'attributes' && mutations[i].attributeName === 'x-data') {
+            const xAttr = mutations[i].target.getAttribute('x-data') || '{}';
+            const rawData = saferEval(this.$el, xAttr, {
+              $el: this.$el
+            });
+            Object.keys(rawData).forEach(key => {
+              if (this.$data[key] !== rawData[key]) {
+                this.$data[key] = rawData[key];
+              }
+            });
+          }
+
+          if (mutations[i].addedNodes.length > 0) {
+            mutations[i].addedNodes.forEach(node => {
+              if (node.nodeType !== 1 || node.__x_inserted_me) return;
+
+              if (node.matches('[x-data]') && !node.__x) {
+                node.__x = new Component(node);
+                return;
+              }
+
+              node.__x_node_add_count = (node.__x_node_add_count || 0) + 1;
+              this.initializeElements(node);
+            });
+          }
+        }
+      });
+      observer.observe(targetNode, observerOptions);
+    }
+
+    getRefsProxy() {
+      var self = this;
+      var refObj = {};
+      // One of the goals of this is to not hold elements in memory, but rather re-evaluate
+      // the DOM when the system needs something from it. This way, the framework is flexible and
+      // friendly to outside DOM changes from libraries like Vue/Livewire.
+      // For this reason, I'm using an "on-demand" proxy to fake a "$refs" object.
+
+      return new Proxy(refObj, {
+        get(object, property) {
+          if (property === '$isAlpineProxy') return true;
+          var ref; // We can't just query the DOM because it's hard to filter out refs in
+          // nested components.
+
+          self.walkAndSkipNestedComponents(self.$el, el => {
+            if (el.hasAttribute('x-ref') && el.getAttribute('x-ref') === property) {
+              ref = el;
+            }
+          });
+          return ref;
+        }
+
+      });
+    }
+
+  }
+
+  const Alpine = {
+    version: "2.8.2",
+    pauseMutationObserver: false,
+    magicProperties: {},
+    onComponentInitializeds: [],
+    onBeforeComponentInitializeds: [],
+    ignoreFocusedForValueBinding: false,
+    start: async function start() {
+      if (!isTesting()) {
+        await domReady();
+      }
+
+      this.discoverComponents(el => {
+        this.initializeComponent(el);
+      }); // It's easier and more performant to just support Turbolinks than listen
+      // to MutationObserver mutations at the document level.
+
+      document.addEventListener("turbolinks:load", () => {
+        this.discoverUninitializedComponents(el => {
+          this.initializeComponent(el);
+        });
+      });
+      this.listenForNewUninitializedComponentsAtRunTime();
+    },
+    discoverComponents: function discoverComponents(callback) {
+      const rootEls = document.querySelectorAll('[x-data]');
+      rootEls.forEach(rootEl => {
+        callback(rootEl);
+      });
+    },
+    discoverUninitializedComponents: function discoverUninitializedComponents(callback, el = null) {
+      const rootEls = (el || document).querySelectorAll('[x-data]');
+      Array.from(rootEls).filter(el => el.__x === undefined).forEach(rootEl => {
+        callback(rootEl);
+      });
+    },
+    listenForNewUninitializedComponentsAtRunTime: function listenForNewUninitializedComponentsAtRunTime() {
+      const targetNode = document.querySelector('body');
+      const observerOptions = {
+        childList: true,
+        attributes: true,
+        subtree: true
+      };
+      const observer = new MutationObserver(mutations => {
+        if (this.pauseMutationObserver) return;
+
+        for (let i = 0; i < mutations.length; i++) {
+          if (mutations[i].addedNodes.length > 0) {
+            mutations[i].addedNodes.forEach(node => {
+              // Discard non-element nodes (like line-breaks)
+              if (node.nodeType !== 1) return; // Discard any changes happening within an existing component.
+              // They will take care of themselves.
+
+              if (node.parentElement && node.parentElement.closest('[x-data]')) return;
+              this.discoverUninitializedComponents(el => {
+                this.initializeComponent(el);
+              }, node.parentElement);
+            });
+          }
+        }
+      });
+      observer.observe(targetNode, observerOptions);
+    },
+    initializeComponent: function initializeComponent(el) {
+      if (!el.__x) {
+        // Wrap in a try/catch so that we don't prevent other components
+        // from initializing when one component contains an error.
+        try {
+          el.__x = new Component(el);
+        } catch (error) {
+          setTimeout(() => {
+            throw error;
+          }, 0);
+        }
+      }
+    },
+    clone: function clone(component, newEl) {
+      if (!newEl.__x) {
+        newEl.__x = new Component(newEl, component);
+      }
+    },
+    addMagicProperty: function addMagicProperty(name, callback) {
+      this.magicProperties[name] = callback;
+    },
+    onComponentInitialized: function onComponentInitialized(callback) {
+      this.onComponentInitializeds.push(callback);
+    },
+    onBeforeComponentInitialized: function onBeforeComponentInitialized(callback) {
+      this.onBeforeComponentInitializeds.push(callback);
+    }
+  };
+
+  if (!isTesting()) {
+    window.Alpine = Alpine;
+
+    if (window.deferLoadingAlpine) {
+      window.deferLoadingAlpine(function () {
+        window.Alpine.start();
+      });
+    } else {
+      window.Alpine.start();
+    }
+  }
+
+  return Alpine;
+
+})));

+ 67 - 0
api-v12/public/assets/typhoon/js/appearance.js

@@ -0,0 +1,67 @@
+((function(global) {
+  const DATA = JSON.parse(document.documentElement.dataset.appearance || 'null');
+  const matchMedia = window.matchMedia('(prefers-color-scheme: dark)');
+
+  try {
+    // Chrome & Firefox
+    matchMedia.addEventListener('change', (event) => {
+      if (typhoonRetrieve().appearance === 'system') {
+        typhoonSetTheme(event.matches ? 'dark' : 'light', true);
+      }
+    });
+  } catch (fallback) {
+    try {
+      // Safari
+      matchMedia.addListener((event) => {
+        if (typhoonRetrieve().appearance === 'system') {
+          typhoonSetTheme(event.matches ? 'dark' : 'light', true);
+        }
+      });
+    } catch (error) {
+      console.error(error);
+    }
+  }
+
+  global.typhoonStore = function(data) {
+    const STORAGE = DATA.store ? 'localStorage' : 'sessionStorage';
+    const theme = data.appearance === 'system' ? typhoonGetTheme() : data.appearance;
+    const config = Object.assign({}, typhoonRetrieve(), data, { theme: theme });
+    global[STORAGE].setItem('typhoon-appearance', JSON.stringify(config));
+    typhoonSetTheme(theme, false);
+  }
+
+  global.typhoonRetrieve = function() {
+    const STORAGE = DATA.store ? 'localStorage' : 'sessionStorage';
+    const systemTheme = typhoonGetTheme();
+    const storage = JSON.parse(global[STORAGE].getItem('typhoon-appearance') || 'null');
+
+    if (storage && storage.appearance === 'system') {
+      storage.theme = systemTheme;
+    }
+
+    return storage || {
+      theme: DATA.appearance === 'system' ? systemTheme : DATA.appearance,
+      appearance: DATA.appearance || 'system'
+    };
+  }
+
+  global.typhoonSetTheme = function(theme, store) {
+    const event = new CustomEvent('typhoon-theme', {
+      detail: {
+        theme: theme,
+        appearance: typhoonRetrieve().appearance
+      }
+    });
+
+    if (store) {
+      typhoonStore({ theme: theme || typhoonGetTheme() });
+    }
+
+    window.dispatchEvent(event);
+  }
+
+  global.typhoonGetTheme = function() {
+    return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
+  }
+
+})(window));

Різницю між файлами не показано, бо вона завелика
+ 0 - 0
api-v12/public/assets/typhoon/js/glightbox.min.js


Деякі файли не було показано, через те що забагато файлів було змінено