git.iko.soy/rowtype-yoga/psfp
on master help sign in
Working on layout
21e940eMark Eibes
.storybook/preview-head.html+1−1
@@ -1,2 +1,2 @@
1−<link href="https://fonts.googleapis.com/css?Montserrat:300,400,500,600,700,800,900&display=swap" rel="stylesheet">
1+<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,500,600,700,800,900&display=swap" rel="stylesheet">
2<style> html, body, #app { min-height: 100%; min-width: 100% }</style>
2<style> html, body, #app { min-height: 100%; min-width: 100% }</style>
assets/alternative.svg+1−1
@@ -1 +1 @@
1−<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g id="Alternative"><path d="M83.506,45.907l-15.824,-15.832l-4.268,4.269l13.688,13.696l-13.688,13.695l4.268,4.268l15.824,-15.826c0.57,-0.573 0.885,-1.332 0.885,-2.139c-0.002,-0.807 -0.315,-1.563 -0.885,-2.131" style="fill:#fff;fill-rule:nonzero;"/><path d="M36.924,34.346l-4.27,-4.27l-15.83,15.829c-0.568,0.568 -0.882,1.328 -0.88,2.134c0,0.807 0.312,1.565 0.88,2.133l15.83,15.83l4.27,-4.267l-13.695,-13.696l13.695,-13.693Z" style="fill:#fff;fill-rule:nonzero;"/><path d="M53.013,18.146c0,-0.714 -0.579,-1.294 -1.293,-1.294l-2.588,0c-0.714,0 -1.294,0.58 -1.294,1.294l0,59.785c0,0.714 0.58,1.294 1.294,1.294l2.588,0c0.714,0 1.293,-0.58 1.293,-1.294l0,-59.785Z" style="fill:#fff;"/></g></g></svg>
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g id="Alternative"><path d="M83.506,45.907l-15.824,-15.832l-4.268,4.269l13.688,13.696l-13.688,13.695l4.268,4.268l15.824,-15.826c0.57,-0.573 0.885,-1.332 0.885,-2.139c-0.002,-0.807 -0.315,-1.563 -0.885,-2.131" style="fill-rule:nonzero;"/><path d="M36.924,34.346l-4.27,-4.27l-15.83,15.829c-0.568,0.568 -0.882,1.328 -0.88,2.134c0,0.807 0.312,1.565 0.88,2.133l15.83,15.83l4.27,-4.267l-13.695,-13.696l13.695,-13.693Z" style="fill-rule:nonzero;"/><path d="M53.013,18.146c0,-0.714 -0.579,-1.294 -1.293,-1.294l-2.588,0c-0.714,0 -1.294,0.58 -1.294,1.294l0,59.785c0,0.714 0.58,1.294 1.294,1.294l2.588,0c0.714,0 1.293,-0.58 1.293,-1.294l0,-59.785Z" style=""/></g></g></svg>
assets/ap.svg+1−1
@@ -1 +1 @@
1−<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="Ap"><g><path d="M90.506,47.156l-15.824,-15.832l-4.268,4.269l13.688,13.696l-13.688,13.695l4.268,4.268l15.824,-15.826c0.57,-0.573 0.885,-1.332 0.885,-2.139c-0.002,-0.807 -0.315,-1.563 -0.885,-2.131" style="fill:#fff;fill-rule:nonzero;"/></g><path d="M29.924,35.595l-4.27,-4.27l-15.83,15.829c-0.568,0.568 -0.882,1.328 -0.88,2.134c0,0.807 0.312,1.565 0.88,2.133l15.83,15.83l4.27,-4.267l-13.695,-13.696l13.695,-13.693Z" style="fill:#fff;fill-rule:nonzero;"/><path d="M47.276,31.405c0.168,-1.47 1.413,-2.58 2.893,-2.58c1.48,0 2.724,1.11 2.893,2.58l1.124,9.784l9.653,-1.954c1.451,-0.294 2.891,0.547 3.348,1.954c0.457,1.408 -0.214,2.934 -1.56,3.549l-8.958,4.093l4.842,8.576c0.727,1.289 0.373,2.918 -0.824,3.788c-1.198,0.87 -2.857,0.704 -3.858,-0.386l-6.66,-7.255l-6.661,7.255c-1,1.09 -2.66,1.256 -3.857,0.386c-1.197,-0.87 -1.552,-2.499 -0.824,-3.788l4.842,-8.576l-8.958,-4.093c-1.347,-0.615 -2.017,-2.141 -1.56,-3.549c0.457,-1.407 1.897,-2.248 3.348,-1.954l9.653,1.954l1.124,-9.784Z" style="fill:#fff;"/></g></g></g></svg>
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="Ap"><g><path d="M90.506,47.156l-15.824,-15.832l-4.268,4.269l13.688,13.696l-13.688,13.695l4.268,4.268l15.824,-15.826c0.57,-0.573 0.885,-1.332 0.885,-2.139c-0.002,-0.807 -0.315,-1.563 -0.885,-2.131" style="fill-rule:nonzero;"/></g><path d="M29.924,35.595l-4.27,-4.27l-15.83,15.829c-0.568,0.568 -0.882,1.328 -0.88,2.134c0,0.807 0.312,1.565 0.88,2.133l15.83,15.83l4.27,-4.267l-13.695,-13.696l13.695,-13.693Z" style="fill-rule:nonzero;"/><path d="M47.276,31.405c0.168,-1.47 1.413,-2.58 2.893,-2.58c1.48,0 2.724,1.11 2.893,2.58l1.124,9.784l9.653,-1.954c1.451,-0.294 2.891,0.547 3.348,1.954c0.457,1.408 -0.214,2.934 -1.56,3.549l-8.958,4.093l4.842,8.576c0.727,1.289 0.373,2.918 -0.824,3.788c-1.198,0.87 -2.857,0.704 -3.858,-0.386l-6.66,-7.255l-6.661,7.255c-1,1.09 -2.66,1.256 -3.857,0.386c-1.197,-0.87 -1.552,-2.499 -0.824,-3.788l4.842,-8.576l-8.958,-4.093c-1.347,-0.615 -2.017,-2.141 -1.56,-3.549c0.457,-1.407 1.897,-2.248 3.348,-1.954l9.653,1.954l1.124,-9.784Z" style=""/></g></g></g></svg>
assets/append.svg+1−1
@@ -1 +1 @@
1−<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="append"><g><path d="M77.506,45.907l-15.824,-15.832l-4.268,4.269l13.688,13.696l-13.688,13.695l4.268,4.268l15.824,-15.826c0.57,-0.573 0.885,-1.332 0.885,-2.139c-0.002,-0.807 -0.315,-1.563 -0.885,-2.131" style="fill:#fff;fill-rule:nonzero;"/></g><path d="M42.924,34.346l-4.27,-4.27l-15.83,15.829c-0.568,0.568 -0.882,1.328 -0.88,2.134c0,0.807 0.312,1.565 0.88,2.133l15.83,15.83l4.27,-4.267l-13.695,-13.696l13.695,-13.693Z" style="fill:#fff;fill-rule:nonzero;"/></g></g></g></svg>
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="append"><g><path d="M77.506,45.907l-15.824,-15.832l-4.268,4.269l13.688,13.696l-13.688,13.695l4.268,4.268l15.824,-15.826c0.57,-0.573 0.885,-1.332 0.885,-2.139c-0.002,-0.807 -0.315,-1.563 -0.885,-2.131" style="fill-rule:nonzero;"/></g><path d="M42.924,34.346l-4.27,-4.27l-15.83,15.829c-0.568,0.568 -0.882,1.328 -0.88,2.134c0,0.807 0.312,1.565 0.88,2.133l15.83,15.83l4.27,-4.267l-13.695,-13.696l13.695,-13.693Z" style="fill-rule:nonzero;"/></g></g></g></svg>
assets/apply.svg+1−1
@@ -1 +1 @@
1−<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.5;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="Apply"><g><path d="M37.344,58.583c0,5.756 5.739,10.422 12.819,10.422c7.075,0 12.818,-4.67 12.818,-10.422c0,-5.754 -5.733,-10.418 -12.807,-10.423l-0.013,0.002c-7.074,-0.005 -12.808,-4.67 -12.808,-10.423c0,-5.752 5.744,-10.423 12.819,-10.423c7.079,0 12.819,4.667 12.819,10.423" style="fill:none;stroke:#fff;stroke-width:6px;"/><path d="M53.012,18.146c0,-0.714 -0.58,-1.294 -1.294,-1.294l-2.588,0c-0.714,0 -1.293,0.58 -1.293,1.294l0,59.785c0,0.714 0.579,1.294 1.293,1.294l2.588,0c0.714,0 1.294,-0.58 1.294,-1.294l0,-59.785Z" style="fill:#fff;"/></g></g></g></g></svg>
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.5;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="Apply"><g><path d="M37.344,58.583c0,5.756 5.739,10.422 12.819,10.422c7.075,0 12.818,-4.67 12.818,-10.422c0,-5.754 -5.733,-10.418 -12.807,-10.423l-0.013,0.002c-7.074,-0.005 -12.808,-4.67 -12.808,-10.423c0,-5.752 5.744,-10.423 12.819,-10.423c7.079,0 12.819,4.667 12.819,10.423" style="fill:none;stroke:#fff;stroke-width:6px;"/><path d="M53.012,18.146c0,-0.714 -0.58,-1.294 -1.294,-1.294l-2.588,0c-0.714,0 -1.293,0.58 -1.293,1.294l0,59.785c0,0.714 0.579,1.294 1.293,1.294l2.588,0c0.714,0 1.294,-0.58 1.294,-1.294l0,-59.785Z" style=""/></g></g></g></g></svg>
assets/applyflipped.svg+1−1
@@ -1 +1 @@
1−<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="Map-Flipped" serif:id="Map Flipped"><path d="M48.556,27.619c0.113,-0.67 -0.34,-1.214 -1.01,-1.214l-2.429,0c-0.67,0 -1.306,0.544 -1.419,1.214l-6.89,40.839c-0.113,0.67 0.339,1.214 1.009,1.214l2.429,0c0.67,0 1.306,-0.544 1.419,-1.214l6.891,-40.839Z" style="fill:#fff;"/><path d="M62.429,27.619c0.113,-0.67 -0.339,-1.214 -1.009,-1.214l-2.429,0c-0.67,0 -1.306,0.544 -1.419,1.214l-6.89,40.839c-0.113,0.67 0.339,1.214 1.009,1.214l2.429,0c0.67,0 1.306,-0.544 1.419,-1.214l6.89,-40.839Z" style="fill:#fff;"/><path d="M67.974,43.53c0.69,0 1.341,-0.544 1.454,-1.214l0.41,-2.429c0.113,-0.67 -0.355,-1.214 -1.044,-1.214l-35.19,0c-0.69,0 -1.341,0.544 -1.454,1.214l-0.41,2.429c-0.113,0.67 0.355,1.214 1.044,1.214l35.19,0Z" style="fill:#fff;"/><path d="M65.633,57.404c0.69,0 1.341,-0.544 1.454,-1.214l0.41,-2.429c0.113,-0.67 -0.355,-1.214 -1.044,-1.214l-35.19,0c-0.689,0 -1.341,0.544 -1.454,1.214l-0.41,2.429c-0.113,0.67 0.355,1.214 1.044,1.214l35.19,0Z" style="fill:#fff;"/></g></g></g></svg>
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="Map-Flipped" serif:id="Map Flipped"><path d="M48.556,27.619c0.113,-0.67 -0.34,-1.214 -1.01,-1.214l-2.429,0c-0.67,0 -1.306,0.544 -1.419,1.214l-6.89,40.839c-0.113,0.67 0.339,1.214 1.009,1.214l2.429,0c0.67,0 1.306,-0.544 1.419,-1.214l6.891,-40.839Z" style=""/><path d="M62.429,27.619c0.113,-0.67 -0.339,-1.214 -1.009,-1.214l-2.429,0c-0.67,0 -1.306,0.544 -1.419,1.214l-6.89,40.839c-0.113,0.67 0.339,1.214 1.009,1.214l2.429,0c0.67,0 1.306,-0.544 1.419,-1.214l6.89,-40.839Z" style=""/><path d="M67.974,43.53c0.69,0 1.341,-0.544 1.454,-1.214l0.41,-2.429c0.113,-0.67 -0.355,-1.214 -1.044,-1.214l-35.19,0c-0.69,0 -1.341,0.544 -1.454,1.214l-0.41,2.429c-0.113,0.67 0.355,1.214 1.044,1.214l35.19,0Z" style=""/><path d="M65.633,57.404c0.69,0 1.341,-0.544 1.454,-1.214l0.41,-2.429c0.113,-0.67 -0.355,-1.214 -1.044,-1.214l-35.19,0c-0.689,0 -1.341,0.544 -1.454,1.214l-0.41,2.429c-0.113,0.67 0.355,1.214 1.044,1.214l35.19,0Z" style=""/></g></g></g></svg>
assets/bind.svg+1−1
@@ -1 +1 @@
1−<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="bind"><g><path d="M53.177,45.907l-15.824,-15.832l-4.268,4.269l13.688,13.696l-13.688,13.695l4.268,4.268l15.824,-15.826c0.57,-0.573 0.885,-1.332 0.885,-2.139c-0.002,-0.807 -0.315,-1.563 -0.885,-2.131" style="fill:#fff;fill-rule:nonzero;"/></g><path d="M15.615,34.346l4.27,-4.27l15.83,15.829c0.568,0.568 0.882,1.328 0.88,2.134c0,0.807 -0.312,1.565 -0.88,2.133l-15.83,15.83l-4.27,-4.267l13.695,-13.696l-13.695,-13.693Z" style="fill:#fff;fill-rule:nonzero;"/><path d="M59.808,43.694l24.911,0l0,-6.262l-31.146,0" style="fill:#fff;"/><path d="M59.808,52.432l24.911,0l0,6.262l-31.146,0" style="fill:#fff;"/></g></g></g></svg>
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="bind"><g><path d="M53.177,45.907l-15.824,-15.832l-4.268,4.269l13.688,13.696l-13.688,13.695l4.268,4.268l15.824,-15.826c0.57,-0.573 0.885,-1.332 0.885,-2.139c-0.002,-0.807 -0.315,-1.563 -0.885,-2.131" style="fill-rule:nonzero;"/></g><path d="M15.615,34.346l4.27,-4.27l15.83,15.829c0.568,0.568 0.882,1.328 0.88,2.134c0,0.807 -0.312,1.565 -0.88,2.133l-15.83,15.83l-4.27,-4.267l13.695,-13.696l-13.695,-13.693Z" style="fill-rule:nonzero;"/><path d="M59.808,43.694l24.911,0l0,-6.262l-31.146,0" style=""/><path d="M59.808,52.432l24.911,0l0,6.262l-31.146,0" style=""/></g></g></g></svg>
assets/compose.svg+1−1
@@ -1 +1 @@
1−<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="compose"><g><path d="M21.829,45.907l15.824,-15.832l4.268,4.269l-13.688,13.696l13.688,13.695l-4.268,4.268l-15.824,-15.826c-0.57,-0.573 -0.885,-1.332 -0.885,-2.139c0.002,-0.807 0.315,-1.563 0.885,-2.131" style="fill:#fff;fill-rule:nonzero;"/></g><path d="M79.391,34.346l-4.27,-4.27l-15.83,15.829c-0.568,0.568 -0.882,1.328 -0.88,2.134c0,0.807 0.312,1.565 0.88,2.133l15.83,15.83l4.27,-4.267l-13.695,-13.696l13.695,-13.693Z" style="fill:#fff;fill-rule:nonzero;"/><path d="M60.656,34.346l-4.27,-4.27l-15.83,15.829c-0.568,0.568 -0.882,1.328 -0.88,2.134c0,0.807 0.312,1.565 0.88,2.133l15.83,15.83l4.27,-4.267l-13.695,-13.696l13.695,-13.693Z" style="fill:#fff;fill-rule:nonzero;"/></g></g></g></svg>
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="compose"><g><path d="M21.829,45.907l15.824,-15.832l4.268,4.269l-13.688,13.696l13.688,13.695l-4.268,4.268l-15.824,-15.826c-0.57,-0.573 -0.885,-1.332 -0.885,-2.139c0.002,-0.807 0.315,-1.563 0.885,-2.131" style="fill-rule:nonzero;"/></g><path d="M79.391,34.346l-4.27,-4.27l-15.83,15.829c-0.568,0.568 -0.882,1.328 -0.88,2.134c0,0.807 0.312,1.565 0.88,2.133l15.83,15.83l4.27,-4.267l-13.695,-13.696l13.695,-13.693Z" style="fill-rule:nonzero;"/><path d="M60.656,34.346l-4.27,-4.27l-15.83,15.829c-0.568,0.568 -0.882,1.328 -0.88,2.134c0,0.807 0.312,1.565 0.88,2.133l15.83,15.83l4.27,-4.267l-13.695,-13.696l13.695,-13.693Z" style="fill-rule:nonzero;"/></g></g></g></svg>
assets/composeflipped.svg+1−1
@@ -1 +1 @@
1−<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><clipPath id="_clip1"><rect id="Artboard11" serif:id="Artboard1" x="0" y="0" width="100" height="100"/></clipPath><g clip-path="url(#_clip1)"><rect id="Background" x="-0.264" y="0.156" width="100.061" height="99.786" style="fill:#1e223f;"/><g id="kleisli"><g><path d="M79.506,47.808l-15.824,-15.832l-4.268,4.269l13.688,13.696l-13.688,13.695l4.268,4.268l15.824,-15.826c0.57,-0.573 0.885,-1.332 0.885,-2.139c-0.002,-0.807 -0.315,-1.563 -0.885,-2.131" style="fill:#fff;fill-rule:nonzero;"/></g><path d="M21.944,36.247l4.27,-4.27l15.83,15.829c0.568,0.568 0.882,1.328 0.88,2.134c0,0.807 -0.312,1.565 -0.88,2.133l-15.83,15.83l-4.27,-4.267l13.695,-13.696l-13.695,-13.693Z" style="fill:#fff;fill-rule:nonzero;"/><path d="M40.679,36.247l4.27,-4.27l15.83,15.829c0.568,0.568 0.882,1.328 0.88,2.134c0,0.807 -0.312,1.565 -0.88,2.133l-15.83,15.83l-4.27,-4.267l13.695,-13.696l-13.695,-13.693Z" style="fill:#fff;fill-rule:nonzero;"/></g></g></svg>
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><clipPath id="_clip1"><rect id="Artboard11" serif:id="Artboard1" x="0" y="0" width="100" height="100"/></clipPath><g clip-path="url(#_clip1)"><rect id="Background" x="-0.264" y="0.156" width="100.061" height="99.786" style="fill:#1e223f;"/><g id="kleisli"><g><path d="M79.506,47.808l-15.824,-15.832l-4.268,4.269l13.688,13.696l-13.688,13.695l4.268,4.268l15.824,-15.826c0.57,-0.573 0.885,-1.332 0.885,-2.139c-0.002,-0.807 -0.315,-1.563 -0.885,-2.131" style="fill-rule:nonzero;"/></g><path d="M21.944,36.247l4.27,-4.27l15.83,15.829c0.568,0.568 0.882,1.328 0.88,2.134c0,0.807 -0.312,1.565 -0.88,2.133l-15.83,15.83l-4.27,-4.267l13.695,-13.696l-13.695,-13.693Z" style="fill-rule:nonzero;"/><path d="M40.679,36.247l4.27,-4.27l15.83,15.829c0.568,0.568 0.882,1.328 0.88,2.134c0,0.807 -0.312,1.565 -0.88,2.133l-15.83,15.83l-4.27,-4.267l13.695,-13.696l-13.695,-13.693Z" style="fill-rule:nonzero;"/></g></g></svg>
assets/forall.svg+1−1
@@ -1 +1 @@
1−<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="forall"><path d="M29.639,24.185l6.269,0l5.743,15.779l17.032,0l5.743,-15.779l6.27,0l-17.363,47.707l-6.331,0l-17.363,-47.707Zm13.872,20.89l6.656,18.287l6.656,-18.287l-13.312,0Z" style="fill:#fff;"/></g></g></g></svg>
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="forall"><path d="M29.639,24.185l6.269,0l5.743,15.779l17.032,0l5.743,-15.779l6.27,0l-17.363,47.707l-6.331,0l-17.363,-47.707Zm13.872,20.89l6.656,18.287l6.656,-18.287l-13.312,0Z" style=""/></g></g></g></svg>
assets/kleisli.svg+1−1
@@ -1 +1 @@
1−<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="kleisli"><g><path d="M86.006,45.907l-15.824,-15.832l-4.268,4.269l13.688,13.696l-13.688,13.695l4.268,4.268l15.824,-15.826c0.57,-0.573 0.885,-1.332 0.885,-2.139c-0.002,-0.807 -0.315,-1.563 -0.885,-2.131" style="fill:#fff;fill-rule:nonzero;"/></g><path d="M13.444,34.346l4.27,-4.27l15.83,15.829c0.568,0.568 0.882,1.328 0.88,2.134c0,0.807 -0.312,1.565 -0.88,2.133l-15.83,15.83l-4.27,-4.267l13.695,-13.696l-13.695,-13.693Z" style="fill:#fff;fill-rule:nonzero;"/><path d="M38.637,43.694l30.063,-0.014l-6.152,-6.248l-30.146,0" style="fill:#fff;"/><path d="M38.637,52.432l30.063,0l-6.152,6.262l-30.146,0" style="fill:#fff;"/></g></g></g></svg>
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="kleisli"><g><path d="M86.006,45.907l-15.824,-15.832l-4.268,4.269l13.688,13.696l-13.688,13.695l4.268,4.268l15.824,-15.826c0.57,-0.573 0.885,-1.332 0.885,-2.139c-0.002,-0.807 -0.315,-1.563 -0.885,-2.131" style="fill-rule:nonzero;"/></g><path d="M13.444,34.346l4.27,-4.27l15.83,15.829c0.568,0.568 0.882,1.328 0.88,2.134c0,0.807 -0.312,1.565 -0.88,2.133l-15.83,15.83l-4.27,-4.267l13.695,-13.696l-13.695,-13.693Z" style="fill-rule:nonzero;"/><path d="M38.637,43.694l30.063,-0.014l-6.152,-6.248l-30.146,0" style=""/><path d="M38.637,52.432l30.063,0l-6.152,6.262l-30.146,0" style=""/></g></g></g></svg>
assets/map.svg+1−1
@@ -1 +1 @@
1−<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.5;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="Map"><path d="M90.506,45.907l-15.824,-15.832l-4.268,4.269l13.688,13.696l-13.688,13.695l4.268,4.268l15.824,-15.826c0.57,-0.573 0.885,-1.332 0.885,-2.139c-0.002,-0.807 -0.315,-1.563 -0.885,-2.131" style="fill:#fff;fill-rule:nonzero;"/><path d="M29.924,34.346l-4.27,-4.27l-15.83,15.829c-0.568,0.568 -0.882,1.328 -0.88,2.134c0,0.807 0.312,1.565 0.88,2.133l15.83,15.83l4.27,-4.267l-13.695,-13.696l13.695,-13.693Z" style="fill:#fff;fill-rule:nonzero;"/><g><path d="M37.346,58.583c0,5.756 5.739,10.422 12.818,10.422c7.075,0 12.819,-4.67 12.819,-10.422c0,-5.754 -5.733,-10.418 -12.808,-10.423l-0.012,0.002c-7.075,-0.005 -12.808,-4.67 -12.808,-10.423c0,-5.752 5.744,-10.423 12.818,-10.423c7.08,0 12.819,4.667 12.819,10.423" style="fill:none;stroke:#fff;stroke-width:6px;"/><path d="M53.013,18.146c0,-0.714 -0.579,-1.294 -1.293,-1.294l-2.588,0c-0.714,0 -1.294,0.58 -1.294,1.294l0,59.785c0,0.714 0.58,1.294 1.294,1.294l2.588,0c0.714,0 1.293,-0.58 1.293,-1.294l0,-59.785Z" style="fill:#fff;"/></g></g></g></g></svg>
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g id="Map"><path d="M90.506,45.907l-15.824,-15.832l-4.268,4.269l13.688,13.696l-13.688,13.695l4.268,4.268l15.824,-15.826c0.57,-0.573 0.885,-1.332 0.885,-2.139c-0.002,-0.807 -0.315,-1.563 -0.885,-2.131" style="fill-rule:nonzero;"/><path d="M29.924,34.346l-4.27,-4.27l-15.83,15.829c-0.568,0.568 -0.882,1.328 -0.88,2.134c0,0.807 0.312,1.565 0.88,2.133l15.83,15.83l4.27,-4.267l-13.695,-13.696l13.695,-13.693Z" style="fill-rule:nonzero;"/><path d="M51.304,22.848c0.484,0 0.878,0.393 0.878,0.878l0,4.969c5.339,0.735 10.415,4.272 10.951,10.001c0.027,0.289 0.039,0.579 0.041,0.869l-4.931,0.039c-0.023,-2.934 -2.79,-5.107 -6.061,-5.828l0,12.109c1.468,0.218 3.352,0.65 4.937,1.5c4.967,2.661 7.895,9.181 4.515,14.545c-1.991,3.157 -5.6,5.051 -9.452,5.574l0,4.847c0,0.485 -0.394,0.878 -0.878,0.878l-1.756,0c-0.485,0 -0.878,-0.393 -0.878,-0.878l0,-4.75c-4.77,-0.384 -9.281,-2.894 -10.969,-7.726c-0.351,-1.007 -0.529,-2.071 -0.537,-3.139l4.931,-0.039c0.024,3.085 3.085,5.33 6.575,5.927l0,-12.096c-0.618,-0.06 -1.308,-0.154 -1.945,-0.301c-5.207,-1.206 -10.046,-5.836 -9.512,-11.531c0.5,-5.342 5.647,-9.416 11.457,-10.055l0,-4.915c0,-0.485 0.393,-0.878 0.878,-0.878l1.756,0Zm0.878,27.969l0,11.83c2.136,-0.357 4.109,-1.432 5.32,-3.411c0.745,-1.22 0.945,-2.758 0.448,-4.118c-0.852,-2.328 -3.189,-3.791 -5.768,-4.301Zm-3.512,-17.235c-2.331,0.263 -4.527,1.346 -5.834,3.483c-0.745,1.22 -0.945,2.758 -0.448,4.118c0.908,2.482 3.504,3.981 6.282,4.389l0,-11.99Z" style=""/></g></g></svg>
assets/mapflipped.svg+1−1
@@ -1 +1 @@
1−<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="Map-Flipped" serif:id="Map Flipped"><g><path d="M90.506,47.151l-15.824,-15.832l-4.268,4.269l13.688,13.696l-13.688,13.695l4.268,4.268l15.824,-15.826c0.57,-0.573 0.885,-1.332 0.885,-2.139c-0.002,-0.807 -0.315,-1.563 -0.885,-2.131" style="fill:#fff;fill-rule:nonzero;"/></g><path d="M29.924,35.59l-4.27,-4.27l-15.83,15.829c-0.568,0.568 -0.882,1.328 -0.88,2.134c0,0.807 0.312,1.565 0.88,2.133l15.83,15.83l4.27,-4.267l-13.695,-13.696l13.695,-13.693Z" style="fill:#fff;fill-rule:nonzero;"/><path d="M48.556,27.619c0.113,-0.67 -0.34,-1.214 -1.01,-1.214l-2.429,0c-0.67,0 -1.306,0.544 -1.419,1.214l-6.89,40.839c-0.113,0.67 0.339,1.214 1.009,1.214l2.429,0c0.67,0 1.306,-0.544 1.419,-1.214l6.891,-40.839Z" style="fill:#fff;"/><path d="M62.429,27.619c0.113,-0.67 -0.339,-1.214 -1.009,-1.214l-2.429,0c-0.67,0 -1.306,0.544 -1.419,1.214l-6.89,40.839c-0.113,0.67 0.339,1.214 1.009,1.214l2.429,0c0.67,0 1.306,-0.544 1.419,-1.214l6.89,-40.839Z" style="fill:#fff;"/><path d="M67.974,43.53c0.69,0 1.341,-0.544 1.454,-1.214l0.41,-2.429c0.113,-0.67 -0.355,-1.214 -1.044,-1.214l-35.19,0c-0.69,0 -1.341,0.544 -1.454,1.214l-0.41,2.429c-0.113,0.67 0.355,1.214 1.044,1.214l35.19,0Z" style="fill:#fff;"/><path d="M65.633,57.404c0.69,0 1.341,-0.544 1.454,-1.214l0.41,-2.429c0.113,-0.67 -0.355,-1.214 -1.044,-1.214l-35.19,0c-0.689,0 -1.341,0.544 -1.454,1.214l-0.41,2.429c-0.113,0.67 0.355,1.214 1.044,1.214l35.19,0Z" style="fill:#fff;"/></g></g></g></svg>
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="Artboard1" x="0" y="0" width="100" height="100" style="fill:none;"/><g id="Artboard11" serif:id="Artboard1"><g><g id="Map-Flipped" serif:id="Map Flipped"><g><path d="M90.506,47.151l-15.824,-15.832l-4.268,4.269l13.688,13.696l-13.688,13.695l4.268,4.268l15.824,-15.826c0.57,-0.573 0.885,-1.332 0.885,-2.139c-0.002,-0.807 -0.315,-1.563 -0.885,-2.131" style="fill-rule:nonzero;"/></g><path d="M29.924,35.59l-4.27,-4.27l-15.83,15.829c-0.568,0.568 -0.882,1.328 -0.88,2.134c0,0.807 0.312,1.565 0.88,2.133l15.83,15.83l4.27,-4.267l-13.695,-13.696l13.695,-13.693Z" style="fill-rule:nonzero;"/><path d="M48.556,27.619c0.113,-0.67 -0.34,-1.214 -1.01,-1.214l-2.429,0c-0.67,0 -1.306,0.544 -1.419,1.214l-6.89,40.839c-0.113,0.67 0.339,1.214 1.009,1.214l2.429,0c0.67,0 1.306,-0.544 1.419,-1.214l6.891,-40.839Z" style=""/><path d="M62.429,27.619c0.113,-0.67 -0.339,-1.214 -1.009,-1.214l-2.429,0c-0.67,0 -1.306,0.544 -1.419,1.214l-6.89,40.839c-0.113,0.67 0.339,1.214 1.009,1.214l2.429,0c0.67,0 1.306,-0.544 1.419,-1.214l6.89,-40.839Z" style=""/><path d="M67.974,43.53c0.69,0 1.341,-0.544 1.454,-1.214l0.41,-2.429c0.113,-0.67 -0.355,-1.214 -1.044,-1.214l-35.19,0c-0.69,0 -1.341,0.544 -1.454,1.214l-0.41,2.429c-0.113,0.67 0.355,1.214 1.044,1.214l35.19,0Z" style=""/><path d="M65.633,57.404c0.69,0 1.341,-0.544 1.454,-1.214l0.41,-2.429c0.113,-0.67 -0.355,-1.214 -1.044,-1.214l-35.19,0c-0.689,0 -1.341,0.544 -1.454,1.214l-0.41,2.429c-0.113,0.67 0.355,1.214 1.044,1.214l35.19,0Z" style=""/></g></g></g></svg>
assets/pslogo.svg+1−1
@@ -1,3 +1,3 @@
1<?xml version="1.0" encoding="UTF-8"?>
1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
2<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
3−<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><g fill="#fff" fill-rule="nonzero"><path d="m69.418 69.64l-7.256-6.775h-31.862l7.256 6.775h31.862z"/><path d="m37.556 45.889l-7.256 6.775h31.863l7.255-6.775h-31.862z"/><path d="m69.416 35.686l-7.254-6.777h-31.86l7.254 6.777h31.86z"/><path d="m26.948 42.391l-4.794-4.793-17.772 17.77c-0.638 0.638-0.99 1.491-0.988 2.396 0 0.906 0.35 1.757 0.988 2.395l17.772 17.772 4.794-4.791-15.375-15.376 15.375-15.373z"/><path d="m95.336 38.392l-17.765-17.774-4.792 4.792 15.368 15.377-15.368 15.374 4.792 4.792 17.765-17.767c0.64-0.644 0.994-1.496 0.994-2.402-3e-3 -0.906-0.354-1.754-0.994-2.392"/></g></svg>
3+<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><g fill-rule="nonzero"><path d="m69.418 69.64l-7.256-6.775h-31.862l7.256 6.775h31.862z"/><path d="m37.556 45.889l-7.256 6.775h31.863l7.255-6.775h-31.862z"/><path d="m69.416 35.686l-7.254-6.777h-31.86l7.254 6.777h31.86z"/><path d="m26.948 42.391l-4.794-4.793-17.772 17.77c-0.638 0.638-0.99 1.491-0.988 2.396 0 0.906 0.35 1.757 0.988 2.395l17.772 17.772 4.794-4.791-15.375-15.376 15.375-15.373z"/><path d="m95.336 38.392l-17.765-17.774-4.792 4.792 15.368 15.377-15.368 15.374 4.792 4.792 17.765-17.767c0.64-0.644 0.994-1.496 0.994-2.402-3e-3 -0.906-0.354-1.754-0.994-2.392"/></g></svg>
src/Button/Component.purs+35−14
@@ -1,6 +1,7 @@
1module Button.Component where
1module Button.Component where
2
2
3import Prelude
3import Prelude
4+
4import Data.Foldable (intercalate)
5import Data.Foldable (intercalate)
5import Data.Monoid (guard)
6import Data.Monoid (guard)
6import Effect (Effect)
7import Effect (Effect)
@@ -11,7 +12,7 @@ import React.Basic.Hooks (ReactComponent, component, element)
11import React.Basic.Hooks as React
12import React.Basic.Hooks as React
12import Record (union)
13import Record (union)
13import Theme.Styles (classNames, makeStyles)
14import Theme.Styles (classNames, makeStyles)
14−import Theme.Types (Theme)
15+import Theme.Types (CSSTheme)
15
16
16data ButtonType
17data ButtonType
17 = PlainButton
18 = PlainButton
@@ -36,7 +37,7 @@ mkButton ∷
36 )
37 )
37mkButton = do
38mkButton = do
38 useStyles <-
39 useStyles <-
39− makeStyles \(theme ∷ Theme) ->
40+ makeStyles \(theme ∷ CSSTheme) ->
40 { "@keyframes gradientBG":
41 { "@keyframes gradientBG":
41 css
42 css
42 { "0%": css { backgroundPosition: "0% 50%" }
43 { "0%": css { backgroundPosition: "0% 50%" }
@@ -46,17 +47,31 @@ mkButton = do
46 , btn:
47 , btn:
47 css
48 css
48 { background:
49 { background:
50+ if theme.isLight
51+ then
52+ theme.interfaceColourLightest
53+ else
49− linearGradient
54+ linearGradient
50− [ "180deg", theme.backgroundColourLighter, theme.backgroundColourLight ]
55+ [ theme.interfaceColourLightest
51− , color: theme.foregroundColourDarker
56+ , theme.interfaceColourLighter
57+ ]
58+ , color: theme.textColour
59+ , boxShadow:
60+ if theme.isLight
61+ then "none"
62+ else
52− , boxShadow: "1px 1px 10px rgba(0,0,0,0.66)"
63+ "1px 1px 10px rgba(0,0,0,0.66)"
64+ , border:
65+ if theme.isLight
66+ then "1px solid " <> theme.interfaceColourLighter
67+ else
68+ "none"
53 , borderRadius: "20px"
69 , borderRadius: "20px"
54 , padding: "0px 18px 0px 18px"
70 , padding: "0px 18px 0px 18px"
55 , marginLeft: "2px"
71 , marginLeft: "2px"
56 , marginRight: "2px"
72 , marginRight: "2px"
57 , minWidth: "100px"
73 , minWidth: "100px"
58 , height: "40px"
74 , height: "40px"
59− , borderWidth: "0px"
60 , fontFamily: theme.textFontFamily
75 , fontFamily: theme.textFontFamily
61 , letterSpacing: "0.2em"
76 , letterSpacing: "0.2em"
62 , textTransform: "uppercase"
77 , textTransform: "uppercase"
@@ -66,11 +81,11 @@ mkButton = do
66 { background:
81 { background:
67 linearGradient
82 linearGradient
68 [ "-5deg"
83 [ "-5deg"
69− , theme.backgroundColourDark
84+ , theme.interfaceColourDarker
70 , theme.highlightColourDark
85 , theme.highlightColourDark
71 , theme.highlightColour
86 , theme.highlightColour
72 ]
87 ]
73− , color: theme.foregroundColourLighter
88+ , color: theme.interfaceColourLighter
74 , backgroundSize: "400% 400%, 100% 100%"
89 , backgroundSize: "400% 400%, 100% 100%"
75 , animation: "$gradientBG 3s ease infinite"
90 , animation: "$gradientBG 3s ease infinite"
76 }
91 }
@@ -79,28 +94,34 @@ mkButton = do
79 { background:
94 { background:
80 linearGradient
95 linearGradient
81 [ "180deg"
96 [ "180deg"
82− , theme.backgroundColourLight
97+ , theme.interfaceColourLighter
83− , theme.backgroundColourLighter
98+ , theme.interfaceColourLightest
84 ]
99 ]
85 , boxShadow: "inset 0 0 2px black"
100 , boxShadow: "inset 0 0 2px black"
86 }
101 }
87 , "&:disabled":
102 , "&:disabled":
88 css
103 css
89 { boxShadow: "0 0 0 black"
104 { boxShadow: "0 0 0 black"
90− , background: theme.backgroundColourLight
105+ , background: theme.backgroundColour
106+ , border: "1px dotted " <> theme.interfaceColourLightest
91 , textDecoration: "line-through"
107 , textDecoration: "line-through"
108+ , textDecorationColor: theme.red
92 }
109 }
93 }
110 }
94 , highlightedButton:
111 , highlightedButton:
95 css
112 css
96 { background:
113 { background:
114+ if theme.isLight
115+ then
116+ theme.highlightColour
117+ else
97− linearGradient [ theme.highlightColour, theme.highlightColourDark ]
118+ linearGradient [ theme.highlightColour, theme.highlightColourDark ]
98 , "&:active":
119 , "&:active":
99 css
120 css
100 { background:
121 { background:
101 linearGradient [ theme.highlightColourDark, theme.highlightColour ]
122 linearGradient [ theme.highlightColourDark, theme.highlightColour ]
102 }
123 }
103− , color: theme.foregroundColourLighter
124+ , color: theme.textColour
104 }
125 }
105 }
126 }
106 component "Button" \{ children, buttonType, buttonProps } -> React.do
127 component "Button" \{ children, buttonType, buttonProps } -> React.do
src/Card/Component.purs+14−19
@@ -2,7 +2,6 @@ module Card.Component where
2
2
3import Prelude
3import Prelude
4
4
5−import Data.Foldable (intercalate)
6import Effect (Effect)
5import Effect (Effect)
7import React.Basic (JSX)
6import React.Basic (JSX)
8import React.Basic.DOM (css)
7import React.Basic.DOM (css)
@@ -10,7 +9,7 @@ import React.Basic.DOM as R
10import React.Basic.Hooks (ReactComponent, component)
9import React.Basic.Hooks (ReactComponent, component)
11import React.Basic.Hooks as React
10import React.Basic.Hooks as React
12import Theme.Styles (classNames, makeStyles)
11import Theme.Styles (classNames, makeStyles)
13−import Theme.Types (Theme)
12+import Theme.Types (CSSTheme)
14
13
15mkCard ∷
14mkCard ∷
16 Effect
15 Effect
@@ -20,19 +19,15 @@ mkCard ∷
20 )
19 )
21mkCard = do
20mkCard = do
22 useStyles <-
21 useStyles <-
23− makeStyles \(theme ∷ Theme) ->
22+ makeStyles \(theme ∷ CSSTheme) ->
24 { card:
23 { card:
25 css
24 css
26− { backgroundImage:
27− "linear-gradient("
28− <> intercalate ","
29− [ "46deg"
30− , theme.backgroundColourLighter
25+ { background: theme.backgroundColourLighter
31− , theme.backgroundColourLight
32− ]
33− <> ")"
34− , color: theme.foregroundColour
26+ , color: theme.textColour
27+ , margin: "20px"
28+ , boxShadow:
35− , boxShadow: "1px 1px 20px rgba(0,0,0,0.66)"
29+ "1px 1px 20px rgba(0,0,0,0." <>
30+ (if theme.isLight then "17" else "43") <> ")"
36 , borderRadius: "5px"
31 , borderRadius: "5px"
37 , padding: "36px 40px 32px 40px"
32 , padding: "36px 40px 32px 40px"
38 }
33 }
@@ -55,10 +50,10 @@ mkCardTitle ∷
55 )
50 )
56mkCardTitle = do
51mkCardTitle = do
57 useStyles <-
52 useStyles <-
58− makeStyles \(theme ∷ Theme) ->
53+ makeStyles \(theme ∷ CSSTheme) ->
59 { cardtitle:
54 { cardtitle:
60 css
55 css
61− { color: theme.foregroundColourLighter
56+ { color: theme.textColourLightest
62 , fontSize: "1.2em"
57 , fontSize: "1.2em"
63 , fontWeight: "400"
58 , fontWeight: "400"
64 , fontFamily: theme.headingFontFamily
59 , fontFamily: theme.headingFontFamily
@@ -83,10 +78,10 @@ mkCardSubtitle ∷
83 )
78 )
84mkCardSubtitle = do
79mkCardSubtitle = do
85 useStyles <-
80 useStyles <-
86− makeStyles \(theme ∷ Theme) ->
81+ makeStyles \(theme ∷ CSSTheme) ->
87 { cardtitle:
82 { cardtitle:
88 css
83 css
89− { color: theme.foregroundColourDarker
84+ { color: theme.textColourDarker
90 , opacity: "0.8"
85 , opacity: "0.8"
91 , fontSize: "1.0em"
86 , fontSize: "1.0em"
92 , fontWeight: "500"
87 , fontWeight: "500"
@@ -112,11 +107,11 @@ mkCardContent ∷
112 )
107 )
113mkCardContent = do
108mkCardContent = do
114 useStyles <-
109 useStyles <-
115− makeStyles \(theme ∷ Theme) ->
110+ makeStyles \(theme ∷ CSSTheme) ->
116 { cardContent:
111 { cardContent:
117 css
112 css
118 { fontFamily: theme.textFontFamily
113 { fontFamily: theme.textFontFamily
119− , color: theme.foregroundColourDark
114+ , color: theme.textColourDarker
120 , fontSize: "0.8em"
115 , fontSize: "0.8em"
121 , fontWeight: "300"
116 , fontWeight: "300"
122 , "WebkitFontSmoothing": "subpixel-antialiased"
117 , "WebkitFontSmoothing": "subpixel-antialiased"
src/Container/Component.purs+17−8
@@ -10,12 +10,12 @@ import React.Basic.DOM (css)
10import React.Basic.DOM as R
10import React.Basic.DOM as R
11import React.Basic.Hooks ((/\), ReactComponent, component, element, useState)
11import React.Basic.Hooks ((/\), ReactComponent, component, element, useState)
12import React.Basic.Hooks as React
12import React.Basic.Hooks as React
13−import SVG.Icon (appendIcon, applyflippedIcon, bindIcon, mapIcon, mapflippedIcon)
13+import SVG.Icon (appendIcon, applyflippedIcon, bindIcon, mapIcon)
14import Theme.Provider (mkThemeProvider)
14import Theme.Provider (mkThemeProvider)
15import Theme.Styles (makeStyles)
15import Theme.Styles (makeStyles)
16−import Theme.Types (Theme)
16+import Theme.Types (CSSTheme)
17
17
18−mkContainer ∷ Effect (ReactComponent { theme ∷ Theme, children ∷ Array JSX })
18+mkContainer ∷ Effect (ReactComponent { theme ∷ CSSTheme, children ∷ Array JSX })
19mkContainer = do
19mkContainer = do
20 themeProvider <- mkThemeProvider
20 themeProvider <- mkThemeProvider
21 containerContent <- mkContainerContent
21 containerContent <- mkContainerContent
@@ -33,22 +33,27 @@ mkContainerContent = do
33 sidebar <- mkSidebar
33 sidebar <- mkSidebar
34 header <- mkHeader
34 header <- mkHeader
35 useStyles <-
35 useStyles <-
36− makeStyles \(theme ∷ Theme) ->
36+ makeStyles \(theme ∷ CSSTheme)->
37 { container:
37 { container:
38 css
38 css
39 { backgroundColor: theme.backgroundColour
39 { backgroundColor: theme.backgroundColour
40 , fontFamily: theme.textFontFamily
40 , fontFamily: theme.textFontFamily
41− , color: theme.foregroundColour
41+ , color: theme.textColour
42 , display: "grid"
42 , display: "grid"
43+ , transition: "0.2s ease-in-out"
43 , gridTemplateAreas:
44 , gridTemplateAreas:
45+ "'landing landing landing'"
44− "'nav header header' "
46+ <> "'header header header' "
45− <> "'nav content content'"
47+ <> "'nav content content'"
46 -- , "footer footer footer"
48 -- , "footer footer footer"
47 -- , gridTemplateColumns: "max-content auto"
49 -- , gridTemplateColumns: "max-content auto"
48 , minWidth: "100%"
50 , minWidth: "100%"
49 , minHeight: "100%"
51 , minHeight: "100%"
52+ , height: "5000px"
50 }
53 }
54+ , landing: css { width: "100vw", height: "100vh", gridArea: "landing" }
51 , content: css { gridArea: "content" }
55 , content: css { gridArea: "content" }
56+ , icon: css { fill: "theme.textColour" }
52 }
57 }
53 sidebarLink <- mkSidebarLink
58 sidebarLink <- mkSidebarLink
54 component "ContainerContent" \{ children } -> React.do
59 component "ContainerContent" \{ children } -> React.do
@@ -58,7 +63,11 @@ mkContainerContent = do
58 $ R.div
63 $ R.div
59 { className: classes.container
64 { className: classes.container
60 , children:
65 , children:
66+ [ R.img
67+ { src: "https://images.unsplash.com/photo-1537498425277-c283d32ef9db?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9"
68+ , className: classes.landing
69+ }
61− [ element sidebar
70+ , element sidebar
62 { collapsed
71 { collapsed
63 , modifyCollapsed
72 , modifyCollapsed
64 , children:
73 , children:
src/Container/Header.purs+65−7
@@ -2,23 +2,34 @@ module Container.Header where
2
2
3import Prelude
3import Prelude
4
4
5+import Control.Alt ((<|>))
6+import Data.Int (toNumber)
5−import Data.Maybe (Maybe(..))
7+import Data.Maybe (Maybe(..), fromMaybe)
8+import Data.Monoid (guard)
9+import Data.Nullable (null)
10+import Debug.Trace (spy)
6import Effect (Effect)
11import Effect (Effect)
7import React.Basic.DOM (css)
12import React.Basic.DOM (css)
8import React.Basic.DOM as R
13import React.Basic.DOM as R
9−import React.Basic.Hooks (ReactComponent, component, element)
14+import React.Basic.Hooks (ReactComponent, component, element, readRef, readRefMaybe, useEffect, useLayoutEffect, useRef, useState, writeRef, (/\))
10import React.Basic.Hooks as React
15import React.Basic.Hooks as React
11import SVG.Icon (pslogoIcon)
16import SVG.Icon (pslogoIcon)
12import Theme.Styles (makeStyles)
17import Theme.Styles (makeStyles)
13−import Theme.Types (Theme)
18+import Theme.Types (CSSTheme)
14import Typography.Header (HeadingLevel(..), mkH)
19import Typography.Header (HeadingLevel(..), mkH)
20+import Web.Event.Event (EventType(..))
21+import Web.Event.EventTarget (addEventListener, eventListener, removeEventListener)
22+import Web.HTML (window)
23+import Web.HTML.HTMLElement (offsetTop)
24+import Web.HTML.HTMLElement as HTMLElement
25+import Web.HTML.Window (scrollY, toEventTarget)
15
26
16mkHeader ∷ Effect (ReactComponent {})
27mkHeader ∷ Effect (ReactComponent {})
17mkHeader = do
28mkHeader = do
18 h <- mkH
29 h <- mkH
19 useStyles <-
30 useStyles <-
20− makeStyles \(theme ∷ Theme) ->
31+ makeStyles \(theme ∷ CSSTheme) ->
21− { sidebar:
32+ { header:
22 css
33 css
23 { backgroundColor: theme.backgroundColour
34 { backgroundColor: theme.backgroundColour
24 , borderBottom: "1px solid " <> theme.highlightColour
35 , borderBottom: "1px solid " <> theme.highlightColour
@@ -30,15 +41,62 @@ mkHeader = do
30 , width: "100vw"
41 , width: "100vw"
31 , height: "80px"
42 , height: "80px"
32 }
43 }
44+ , sticky: css { position: "fixed", top: "0" }
45+ , logo:
46+ css
47+ { width: "70px"
48+ , height: "70px"
49+ , padding: "5px"
33− , logo: css { width: "70px", height: "70px", padding: "5px", marginRight: "7px" }
50+ , marginRight: "7px"
51+ , fill: theme.textColour
52+ }
34 }
53 }
54+ useScrollYPosition <- mkUseScrollYPosition
35 component "Header" \{} -> React.do
55 component "Header" \{} -> React.do
36 classes <- useStyles
56 classes <- useStyles
57+ mustBeSticky /\ modifyMustBeSticky <- useState false
58+ nodeY /\ modifyNodeY <- useState 0
59+ nodeOffset /\ modifyONP <- useState Nothing
60+ nodeRef <- useRef null
61+ scrollYPos <- useScrollYPosition
62+ useEffect scrollYPos do
63+ maybeNode <- readRefMaybe nodeRef
64+ let maybeElem = maybeNode >>= HTMLElement.fromNode
65+ case maybeElem of
66+ Nothing -> pure (pure unit)
67+ Just element -> do
68+ offset <- offsetTop element
69+ modifyONP case _ of
70+ Just x -> Just x
71+ Nothing -> Just offset
72+ let offset' = fromMaybe offset nodeOffset
73+ modifyMustBeSticky
74+ if toNumber scrollYPos > offset'
75+ then const true
76+ else const false
77+ pure (pure unit)
78+
37 pure
79 pure
38 $ R.header
80 $ R.header
81+ { ref: nodeRef
39− { className: classes.sidebar
82+ , className: classes.header <> " " <> guard mustBeSticky classes.sticky
40 , children:
83 , children:
41 [ R.div { children: [ element pslogoIcon {} ], className: classes.logo }
84 [ R.div { children: [ element pslogoIcon {} ], className: classes.logo }
42 , element h { level: H2, text: "Purescript", className: Nothing }
85 , element h { level: H2, text: "Purescript", className: Nothing }
43 ]
86 ]
44 }
87 }
88+
89+mkUseScrollYPosition = do
90+ initialPosition <- window >>= scrollY
91+ pure $ React.do
92+ scrollPosY /\ modifyScrollPosY <- useState initialPosition
93+ useLayoutEffect unit do
94+ target <- window <#> toEventTarget
95+ let eventType = EventType "scroll"
96+ listener <- eventListener
97+ \_ -> window >>= scrollY >>= \newPos -> modifyScrollPosY (const newPos)
98+ addEventListener eventType listener false target
99+ let _ = spy "registered event listener" unit
100+ pure $
101+ removeEventListener eventType listener false target
102+ pure $ scrollPosY
src/Container/Sidebar.purs+9−15
@@ -1,8 +1,7 @@
1module Container.Sidebar where
1module Container.Sidebar where
2
2
3import Prelude
3import Prelude
4−import Card.Component (mkCard, mkCardContent)
4+
5−import Data.Foldable (intercalate)
6import Data.Monoid (guard)
5import Data.Monoid (guard)
7import Effect (Effect)
6import Effect (Effect)
8import React.Basic (JSX)
7import React.Basic (JSX)
@@ -13,7 +12,7 @@ import React.Basic.Hooks (ReactComponent, component, element)
13import React.Basic.Hooks as React
12import React.Basic.Hooks as React
14import SVG.Icon (ActiveArrowDirection(..), mkMenu)
13import SVG.Icon (ActiveArrowDirection(..), mkMenu)
15import Theme.Styles (classNames, makeStyles)
14import Theme.Styles (classNames, makeStyles)
16−import Theme.Types (Theme)
15+import Theme.Types (CSSTheme)
17
16
18mkSidebar ∷
17mkSidebar ∷
19 Effect
18 Effect
@@ -25,18 +24,12 @@ mkSidebar ∷
25 )
24 )
26mkSidebar = do
25mkSidebar = do
27 useStyles <-
26 useStyles <-
28− makeStyles \(theme ∷ Theme) ->
27+ makeStyles \(theme ∷ CSSTheme) ->
29 { sidebar:
28 { sidebar:
30 css
29 css
31− { background:
30+ { background: theme.backgroundColour
32− "linear-gradient(-45deg,"
33− <> intercalate ","
34− [ theme.foregroundColourLighter
35− , theme.foregroundColourLight
36− ]
37− <> ")"
38 , fontFamily: theme.textFontFamily
31 , fontFamily: theme.textFontFamily
39− , color: theme.foregroundColour
32+ , color: theme.textColour
40 , gridArea: "nav"
33 , gridArea: "nav"
41 , display: "flex"
34 , display: "flex"
42 , flexDirection: "column"
35 , flexDirection: "column"
@@ -87,14 +80,14 @@ mkSidebar = do
87mkSidebarLink ∷ Effect (ReactComponent { name ∷ String, icon ∷ JSX, collapsed ∷ Boolean })
80mkSidebarLink ∷ Effect (ReactComponent { name ∷ String, icon ∷ JSX, collapsed ∷ Boolean })
88mkSidebarLink = do
81mkSidebarLink = do
89 useStyles <-
82 useStyles <-
90− makeStyles \(theme ∷ Theme) ->
83+ makeStyles \(theme ∷ CSSTheme) ->
91 { sidebarEntry:
84 { sidebarEntry:
92 css
85 css
93 { fontFamily: theme.headingFontFamily
86 { fontFamily: theme.headingFontFamily
94 , alignSelf: "flex-end"
87 , alignSelf: "flex-end"
95 , justifyContent: "space-between"
88 , justifyContent: "space-between"
96 , alignContent: "stretch"
89 , alignContent: "stretch"
97− , color: theme.foregroundColour
90+ , color: theme.textColour
98 , gridArea: "nav"
91 , gridArea: "nav"
99 , display: "flex"
92 , display: "flex"
100 , flexDirection: "row"
93 , flexDirection: "row"
@@ -112,7 +105,7 @@ mkSidebarLink = do
112 , label:
105 , label:
113 css
106 css
114 { fontFamily: theme.textFontFamily
107 { fontFamily: theme.textFontFamily
115− , color: theme.backgroundColour
108+ , color: theme.textColour
116 , paddingLeft: "20px"
109 , paddingLeft: "20px"
117 , textTransform: "uppercase"
110 , textTransform: "uppercase"
118 , lineHeight: "60px"
111 , lineHeight: "60px"
@@ -126,6 +119,7 @@ mkSidebarLink = do
126 , transition: "0.2s ease-in-out"
119 , transition: "0.2s ease-in-out"
127 , transitionDelay: "0.1s"
120 , transitionDelay: "0.1s"
128 , alignSelf: "flex-end"
121 , alignSelf: "flex-end"
122+ , fill: theme.textColour <> " !important"
129 }
123 }
130 }
124 }
131 component "SidebarLink" \{ name, icon, collapsed } -> React.do
125 component "SidebarLink" \{ name, icon, collapsed } -> React.do
src/Element.purs+2−2
@@ -12,14 +12,14 @@ import Theme.Provider (mkThemeProvider)
12import Theme.Styles (makeStyles)
12import Theme.Styles (makeStyles)
13import Theme.Types (Theme)
13import Theme.Types (Theme)
14
14
15−mkToggleButton ∷ Effect (ReactComponent { label :: String })
15+mkToggleButton ∷ Effect (ReactComponent { label ∷ String })
16mkToggleButton = do
16mkToggleButton = do
17 useStyles <-
17 useStyles <-
18 makeStyles \(theme ∷ Theme) -> -- do
18 makeStyles \(theme ∷ Theme) -> -- do
19 { button:
19 { button:
20 css
20 css
21 { backgroundColor: theme.highlightColour
21 { backgroundColor: theme.highlightColour
22− , color: theme.foregroundColour
22+ , color: theme.textColour
23 , fontFamily: theme.textFontFamily
23 , fontFamily: theme.textFontFamily
24 , fontSize: "1em"
24 , fontSize: "1em"
25 , paddingTop: "10px"
25 , paddingTop: "10px"
src/SVG/Icon.purs+2−2
@@ -15,7 +15,7 @@ import Unsafe.Coerce (unsafeCoerce)
15
15
16type ImageProps = ( width ∷ Int, height ∷ Int )
16type ImageProps = ( width ∷ Int, height ∷ Int )
17
17
18−type Raw = ReactComponent { width ∷ Int, height ∷ Int }
18+type Raw = ReactComponent { width ∷ Int, height ∷ Int, className ∷ String }
19
19
20foreign import alternativeIconRaw ∷ Raw
20foreign import alternativeIconRaw ∷ Raw
21alternativeIcon ∷ ∀ attrs attrs_. Union attrs attrs_ ImageProps => ReactComponent { | attrs }
21alternativeIcon ∷ ∀ attrs attrs_. Union attrs attrs_ ImageProps => ReactComponent { | attrs }
@@ -79,7 +79,7 @@ mkMenu = do
79 makeStyles \(theme ∷ Theme) ->
79 makeStyles \(theme ∷ Theme) ->
80 { arrow:
80 { arrow:
81 css
81 css
82− { fill: theme.foregroundColour
82+ { fill: theme.textColour
83 , transition: "0.3s ease-out"
83 , transition: "0.3s ease-out"
84 }
84 }
85 , arrowInactive:
85 , arrowInactive:
src/Theme/Default.purs+32−13
@@ -3,19 +3,38 @@ module Theme.Default where
3import Color as Color
3import Color as Color
4import Theme.Types (Theme)
4import Theme.Types (Theme)
5
5
6+lightTheme ∷ Theme
7+lightTheme =
8+ { textColour: Color.hsl 225.0 0.18 0.25
9+ , backgroundColour: Color.hsl 210.0 0.00 0.98
10+ , interfaceColour: Color.hsl 210.0 0.10 0.70
11+ , highlightColour: Color.hsl 150.0 0.55 0.78
12+ , altHighlightColour: Color.hsl 84.0 0.617 0.631
13+ , textFontFamily: ["-apple-system", "BlinkMacSystemFont", "Helvetica", "Arial", "sans-serif"]
14+ , headingFontFamily: ["Montserrat", "Monaco", "sans-serif"]
15+ , yellow: Color.rgb 255 235 149
16+ , green: Color.rgb 173 219 103
17+ , pink: Color.rgb 199 146 234
18+ , orange: Color.rgb 255 203 139
19+ , turquoise: Color.rgb 127 219 202
20+ , red: Color.rgb 255 88 116
21+ , blue: Color.rgb 130 170 255
22+ }
23+
6darkTheme ∷ Theme
24darkTheme ∷ Theme
7darkTheme =
25darkTheme =
26+ { backgroundColour: Color.hsl 215.0 0.28 0.20
8− { backgroundColour: Color.hsl 225.0 0.28 0.20 -- hsl(100, 10%, 50%)
27+ , textColour: Color.hsl 225.0 0.28 0.90
9− , foregroundColour: Color.hsl 220.0 0.22 0.90
28+ , interfaceColour: Color.hsl 215.0 0.28 0.20
10− , highlightColour: Color.rgb 0xb7 0x82 0xda
29+ , highlightColour: Color.rgb 183 130 218
11− , altHighlightColour: Color.hsl 84.0 0.617 0.631
30+ , altHighlightColour: Color.hsl 84.0 0.617 0.631
12− , textFontFamily: ["'Montserrat'", "-apple-system", "BlinkMacSystemFont", "sans-serif"]
31+ , textFontFamily: ["-apple-system", "BlinkMacSystemFont", "Helvetica", "Arial", "sans-serif"]
13− , headingFontFamily: ["'Montserrat'", "sans-serif"]
32+ , headingFontFamily: ["Montserrat", "Monaco", "sans-serif"]
14− , yellow: Color.rgb 0xFF 0xEB 0x95
33+ , yellow: Color.rgb 255 235 149
15− , green: Color.rgb 0xad 0xdb 0x67
34+ , green: Color.rgb 173 219 103
16− , pink: Color.rgb 0xc7 0x92 0xea
35+ , pink: Color.rgb 199 146 234
17− , orange: Color.rgb 0xff 0xcb 0x8b
36+ , orange: Color.rgb 255 203 139
18− , turquoise: Color.rgb 0x7f 0xdb 0xca
37+ , turquoise: Color.rgb 127 219 202
19− , red: Color.rgb 0xff 0x58 0x74
38+ , red: Color.rgb 255 88 116
20− , blue: Color.rgb 0x82 0xAA 0xFF
39+ , blue: Color.rgb 130 170 255
21 }
40 }
src/Theme/Styles.js+1
@@ -4,3 +4,4 @@ var styles = require("@material-ui/styles");
4
4
5exports.makeStylesImpl = styles.makeStyles
5exports.makeStylesImpl = styles.makeStyles
6exports.makeStylesThemedImpl = styles.makeStyles
6exports.makeStylesThemedImpl = styles.makeStyles
7+exports.useThemeImpl = styles.useTheme
src/Theme/Styles.purs+11−2
@@ -1,7 +1,9 @@
1module Theme.Styles
1module Theme.Styles
2 ( makeStyles_
2 ( makeStyles_
3 , makeStyles
3 , makeStyles
4+ , useTheme
4 , UseStyles
5 , UseStyles
6+ , UseTheme
5 , classNames
7 , classNames
6 ) where
8 ) where
7
9
@@ -14,16 +16,17 @@ import Prim.RowList (class RowToList)
14import React.Basic.DOM (CSS)
16import React.Basic.DOM (CSS)
15import React.Basic.Hooks (Hook)
17import React.Basic.Hooks (Hook)
16import Record.Extra (class MapRecord)
18import Record.Extra (class MapRecord)
19+import Theme.Types (CSSTheme)
17import Type.Row.Homogeneous (class Homogeneous)
20import Type.Row.Homogeneous (class Homogeneous)
18
21
19foreign import data UseStyles ∷ Type -> Type -> Type
22foreign import data UseStyles ∷ Type -> Type -> Type
20
23
21foreign import makeStylesImpl ∷
24foreign import makeStylesImpl ∷
22− forall css classNames.
25+ ∀ css classNames.
23 EffectFn1 {|css} (Hook (UseStyles { | css }) { | classNames })
26 EffectFn1 {|css} (Hook (UseStyles { | css }) { | classNames })
24
27
25foreign import makeStylesThemedImpl ∷
28foreign import makeStylesThemedImpl ∷
26− forall theme css classNames.
29+ ∀ theme css classNames.
27 EffectFn1 ({|theme} -> {|css}) (Hook (UseStyles { | css }) { | classNames })
30 EffectFn1 ({|theme} -> {|css}) (Hook (UseStyles { | css }) { | classNames })
28
31
29makeStyles ∷
32makeStyles ∷
@@ -42,5 +45,11 @@ makeStyles_ ∷
42 Effect (Hook (UseStyles { | css }) { | classNames })
45 Effect (Hook (UseStyles { | css }) { | classNames })
43makeStyles_ = runEffectFn1 makeStylesImpl
46makeStyles_ = runEffectFn1 makeStylesImpl
44
47
48+foreign import data UseTheme ∷ Type -> Type
49+foreign import useThemeImpl ∷ ∀ classNames.
50+ Hook (UseTheme ) { | classNames }
51+useTheme ∷ Hook (UseTheme) CSSTheme
52+useTheme = useThemeImpl
53+
45classNames ∷ ∀ r. Homogeneous r String => Array (Record r -> String) -> Record r -> String
54classNames ∷ ∀ r. Homogeneous r String => Array (Record r -> String) -> Record r -> String
46classNames cs allClasses = (cs <#> \x -> x allClasses) # intercalate " "
55classNames cs allClasses = (cs <#> \x -> x allClasses) # intercalate " "
src/Theme/Types.purs+58−29
@@ -2,17 +2,17 @@ module Theme.Types where
2
2
3import Prelude
3import Prelude
4
4
5−import CSS (darken, lighten)
5+import CSS (ColorSpace(..), blue, brightness, darken, desaturate, isLight, lighten, mix, rotateHue)
6import CSS.Color (toHexString)
6import CSS.Color (toHexString)
7import Color (Color)
7import Color (Color)
8import Data.Foldable (intercalate)
8import Data.Foldable (intercalate)
9−import Data.Function (applyFlipped)
10import Data.Symbol (SProxy(..))
9import Data.Symbol (SProxy(..))
11import Record.Builder as RB
10import Record.Builder as RB
12
11
13type Theme =
12type Theme =
14 { backgroundColour ∷ Color
13 { backgroundColour ∷ Color
15− , foregroundColour ∷ Color
14+ , textColour ∷ Color
15+ , interfaceColour ∷ Color
16 , highlightColour ∷ Color
16 , highlightColour ∷ Color
17 , altHighlightColour ∷ Color
17 , altHighlightColour ∷ Color
18 , textFontFamily ∷ Array String
18 , textFontFamily ∷ Array String
@@ -34,31 +34,34 @@ fromTheme theme = RB.build (
34 -- background
34 -- background
35 RB.modify (f ∷ _ "backgroundColour") toHexString
35 RB.modify (f ∷ _ "backgroundColour") toHexString
36 >>> RB.insert (f ∷ _ "backgroundColourLighter")
36 >>> RB.insert (f ∷ _ "backgroundColourLighter")
37− (theme.backgroundColour # lighten 0.2 # toHexString)
37+ (theme.backgroundColour # lighter >>> toHexString)
38− >>> RB.insert (f ∷ _ "backgroundColourLight")
38+ >>> RB.modify (f ∷ _ "interfaceColour") toHexString
39+ >>> RB.insert (f ∷ _ "interfaceColourLighter")
39− (theme.backgroundColour # lighten 0.4 # toHexString)
40+ (theme.interfaceColour # lighter >>> toHexString)
40− >>> RB.insert (f ∷ _ "backgroundColourDarker")
41+ >>> RB.insert (f ∷ _ "interfaceColourLightest")
41− (theme.backgroundColour # darken 0.2 # toHexString)
42+ (theme.interfaceColour # lighter >>> lighter >>> toHexString)
42− >>> RB.insert (f ∷ _ "backgroundColourDark")
43+ >>> RB.insert (f ∷ _ "interfaceColourDarker")
43− (theme.backgroundColour # darken 0.4 # toHexString)
44+ (theme.interfaceColour # darker >>> toHexString)
45+ >>> RB.insert (f ∷ _ "interfaceColourDarkest")
46+ (theme.interfaceColour # darker >>> darker >>> toHexString)
44 -- foreground
47 -- foreground
45− >>> RB.modify (f ∷ _ "foregroundColour") toHexString
48+ >>> RB.modify (f ∷ _ "textColour") toHexString
46− >>> RB.insert (f ∷ _ "foregroundColourLighter")
49+ >>> RB.insert (f ∷ _ "textColourLighter")
47− (theme.foregroundColour # lighten 0.2 # toHexString)
50+ (theme.textColour # lighter >>> toHexString)
48− >>> RB.insert (f ∷ _ "foregroundColourLight")
51+ >>> RB.insert (f ∷ _ "textColourLightest")
49− (theme.foregroundColour # lighten 0.4 # toHexString)
52+ (theme.textColour # lighter >>> lighter >>> toHexString)
50− >>> RB.insert (f ∷ _ "foregroundColourDarker")
53+ >>> RB.insert (f ∷ _ "textColourDarker")
51− (theme.foregroundColour # darken 0.2 # toHexString)
54+ (theme.textColour # darker >>> toHexString)
52− >>> RB.insert (f ∷ _ "foregroundColourDark")
55+ >>> RB.insert (f ∷ _ "textColourDarkest")
53− (theme.foregroundColour # darken 0.4 # toHexString)
56+ (theme.textColour # darker >>> darker >>> toHexString)
54 -- highlight
57 -- highlight
55 >>> RB.modify (f ∷ _ "highlightColour") toHexString
58 >>> RB.modify (f ∷ _ "highlightColour") toHexString
56 >>> RB.insert (f ∷ _ "highlightColourDark")
59 >>> RB.insert (f ∷ _ "highlightColourDark")
57− (theme.highlightColour # darken 0.4 # toHexString)
60+ (theme.highlightColour # darken 0.2 # rotateHue (-10.0) # toHexString)
58 -- altHighlight
61 -- altHighlight
59 >>> RB.modify (f ∷ _ "altHighlightColour") toHexString
62 >>> RB.modify (f ∷ _ "altHighlightColour") toHexString
60 >>> RB.insert (f ∷ _ "altHighlightColourDark")
63 >>> RB.insert (f ∷ _ "altHighlightColourDark")
61− (theme.altHighlightColour # darken 0.4 # toHexString)
64+ (theme.altHighlightColour # darken 0.2 # toHexString)
62 -- palette
65 -- palette
63 >>> RB.modify (f ∷ _ "yellow") toHexString
66 >>> RB.modify (f ∷ _ "yellow") toHexString
64 >>> RB.modify (f ∷ _ "green") toHexString
67 >>> RB.modify (f ∷ _ "green") toHexString
@@ -70,23 +73,49 @@ fromTheme theme = RB.build (
70 -- fonts
73 -- fonts
71 >>> RB.modify (f ∷ _ "textFontFamily") (intercalate ",")
74 >>> RB.modify (f ∷ _ "textFontFamily") (intercalate ",")
72 >>> RB.modify (f ∷ _ "headingFontFamily") (intercalate ",")
75 >>> RB.modify (f ∷ _ "headingFontFamily") (intercalate ",")
76+ >>> RB.insert (f ∷ _ "isLight") isLightTheme
73 ) theme
77 ) theme
78+ where
79+ isLightTheme = isLight theme.backgroundColour
80+ yellower ∷ Color -> Color
81+ yellower col =
82+ if brightness col > 0.8
83+ then
84+ lighten 0.02 col
85+ else
86+ col
87+ # lighten 0.1
88+ # desaturate 0.03
89+
90+ bluer col =
91+ mix HSL col blue 0.05
92+ # darken 0.1
93+ # desaturate 0.03
94+
95+ lighter ∷ Color -> Color
96+ lighter = yellower
97+
98+ darker ∷ Color -> Color
99+ darker = bluer
74
100
75type CSSTheme =
101type CSSTheme =
76 { backgroundColour ∷ String
102 { backgroundColour ∷ String
77− , backgroundColourDarker ∷ String
78− , backgroundColourDark ∷ String
79 , backgroundColourLighter ∷ String
103 , backgroundColourLighter ∷ String
80− , backgroundColourLight ∷ String
104+ , interfaceColour ∷ String
81− , foregroundColourLight ∷ String
105+ , interfaceColourDarker ∷ String
82− , foregroundColourLighter ∷ String
106+ , interfaceColourDarkest ∷ String
83− , foregroundColour ∷ String
107+ , interfaceColourLighter ∷ String
84− , foregroundColourDarker ∷ String
108+ , interfaceColourLightest ∷ String
85− , foregroundColourDark ∷ String
109+ , textColourLightest ∷ String
110+ , textColourLighter ∷ String
111+ , textColour ∷ String
112+ , textColourDarker ∷ String
113+ , textColourDarkest ∷ String
86 , highlightColour ∷ String
114 , highlightColour ∷ String
87 , highlightColourDark ∷ String
115 , highlightColourDark ∷ String
88 , altHighlightColour ∷ String
116 , altHighlightColour ∷ String
89 , altHighlightColourDark ∷ String
117 , altHighlightColourDark ∷ String
118+ , isLight ∷ Boolean
90 , textFontFamily ∷ String
119 , textFontFamily ∷ String
91 , headingFontFamily ∷ String
120 , headingFontFamily ∷ String
92 , yellow ∷ String
121 , yellow ∷ String
src/Typography/Header.purs+5−4
@@ -1,6 +1,7 @@
1module Typography.Header where
1module Typography.Header where
2
2
3import Prelude
3import Prelude
4+
4import Data.Array as Array
5import Data.Array as Array
5import Data.Foldable (intercalate)
6import Data.Foldable (intercalate)
6import Data.Maybe (Maybe)
7import Data.Maybe (Maybe)
@@ -10,7 +11,7 @@ import React.Basic.DOM as R
10import React.Basic.Hooks (ReactComponent, component)
11import React.Basic.Hooks (ReactComponent, component)
11import React.Basic.Hooks as React
12import React.Basic.Hooks as React
12import Theme.Styles (makeStyles)
13import Theme.Styles (makeStyles)
13−import Theme.Types (Theme)
14+import Theme.Types (CSSTheme)
14
15
15data HeadingLevel
16data HeadingLevel
16 = H1
17 = H1
@@ -23,10 +24,10 @@ mkH ∷
23 Effect (ReactComponent { level ∷ HeadingLevel, text ∷ String, className ∷ Maybe String })
24 Effect (ReactComponent { level ∷ HeadingLevel, text ∷ String, className ∷ Maybe String })
24mkH = do
25mkH = do
25 useStyles <-
26 useStyles <-
26− makeStyles \(theme ∷ Theme) ->
27+ makeStyles \(theme ∷ CSSTheme) ->
27 { common:
28 { common:
28 css
29 css
29− { color: theme.foregroundColour
30+ { color: theme.textColour
30 , fontFamily: theme.headingFontFamily
31 , fontFamily: theme.headingFontFamily
31 }
32 }
32 , h1:
33 , h1:
@@ -62,7 +63,7 @@ mkH = do
62 { fontSize: "1.0em"
63 { fontSize: "1.0em"
63 , margin: 0
64 , margin: 0
64 , padding: 0
65 , padding: 0
65− , color: theme.foregroundLowContrastColour
66+ , color: theme.textColourLighter
66 }
67 }
67 }
68 }
68 component "Heading" \{ level, text, className } -> React.do
69 component "Heading" \{ level, text, className } -> React.do
src/Typography/Paragraph.purs+1−1
@@ -15,7 +15,7 @@ mkP = do
15 makeStyles \(theme ∷ Theme) ->
15 makeStyles \(theme ∷ Theme) ->
16 { p:
16 { p:
17 css
17 css
18− { color: theme.foregroundColour
18+ { color: theme.textColour
19 , fontFamily: theme.textFontFamily
19 , fontFamily: theme.textFontFamily
20 , fontSize: "1em"
20 , fontSize: "1em"
21 , margin: "0.67em 0 0.33em 0"
21 , margin: "0.67em 0 0.33em 0"
stories/CardStories.purs+11−5
@@ -5,6 +5,7 @@ import Prelude hiding (add)
5import Card.Component (mkCard, mkCardContent, mkCardSubtitle, mkCardTitle)
5import Card.Component (mkCard, mkCardContent, mkCardSubtitle, mkCardTitle)
6import Decorator.FullScreen (fullScreenDecorator)
6import Decorator.FullScreen (fullScreenDecorator)
7import Effect (Effect)
7import Effect (Effect)
8+import React.Basic.DOM (css)
8import React.Basic.DOM as R
9import React.Basic.DOM as R
9import React.Basic.Hooks (component, element)
10import React.Basic.Hooks (component, element)
10import Storybook.React (Storybook, add, addDecorator, storiesOf)
11import Storybook.React (Storybook, add, addDecorator, storiesOf)
@@ -27,12 +28,17 @@ stories =
27 cardContent <- mkCardContent
28 cardContent <- mkCardContent
28 component "ExampleCard" \{ title, subtitle, content } -> React.do
29 component "ExampleCard" \{ title, subtitle, content } -> React.do
29 pure
30 pure
30− $ element card
31+ $ R.div
31 { children:
32 { children:
33+ pure
34+ $ element card
35+ { children:
32− [ element cardTitle { children: [ R.text title ] }
36+ [ element cardTitle { children: [ R.text title ] }
33− , element cardSubtitle { children: [ R.text subtitle ] }
37+ , element cardSubtitle { children: [ R.text subtitle ] }
34− , element cardContent { children: [ content ] }
38+ , element cardContent { children: [ content ] }
35− ]
39+ ]
40+ }
41+ , style: css { width: "400px" }
36 }
42 }
37
43
38loremIpsum ∷ String
44loremIpsum ∷ String
stories/ContainerStories.purs+18−22
@@ -2,33 +2,29 @@ module ContainerStories where
2
2
3import Prelude hiding (add)
3import Prelude hiding (add)
4import Container.Component (mkContainer)
4import Container.Component (mkContainer)
5+import Decorator.FullScreen (fullScreenDecorator)
5import Effect (Effect)
6import Effect (Effect)
6import React.Basic.DOM (css)
7import React.Basic.DOM (css)
7import React.Basic.DOM as R
8import React.Basic.DOM as R
9+import React.Basic.Hooks (component, element)
10+import React.Basic.Hooks as React
8−import Storybook.React (Storybook, add, storiesOf)
11+import Storybook.React (Storybook, add, addDecorator, storiesOf)
9import Theme.Default (darkTheme)
12import Theme.Default (darkTheme)
13+import Theme.Styles (useTheme)
14+import Theme.Types (fromTheme)
10
15
11stories ∷ Effect Storybook
16stories ∷ Effect Storybook
12stories =
17stories =
13 storiesOf "Container" do
18 storiesOf "Container" do
19+ addDecorator fullScreenDecorator
14− add "Container" mkContainer
20+ add "Container" mkExample [ {} ]
15− [ { theme: darkTheme
21+ where
16− , children:
22+ mkExample = do
17− [ R.h1
23+ container <- mkContainer
18− { children: [ R.text "PURESCRIPT" ]
24+ component "ContainerExample" \{} -> React.do
19− , style:
25+ theme <- useTheme
20− css
26+ pure
21− { textAlign: "center"
27+ $ element container
22− , marginTop: "20px"
28+ { theme
23− , fontSize: "2em"
24− , fontFamily: darkTheme.headingFontFamily
25− , letterSpacing: "0.07em"
26− }
27− }
28− , R.div
29− { children: [ R.text "what the fuck?" ]
29+ , children: []
30− , style: css { height: "400px", textAlign: "center", marginTop: "100px" }
31− }
30+ }
32− ]
33− }
34− ]
stories/Decorator/FullScreen.purs+82−27
@@ -2,43 +2,98 @@ module Decorator.FullScreen where
2
2
3import Prelude
3import Prelude
4
4
5+import Data.Array (find)
6+import Data.Map (Map)
7+import Data.Maybe (Maybe, fromMaybe)
8+import Data.Traversable (traverse_)
5import Effect (Effect)
9import Effect (Effect)
6import React.Basic (JSX)
10import React.Basic (JSX)
7import React.Basic.DOM (css)
11import React.Basic.DOM (css)
8import React.Basic.DOM as R
12import React.Basic.DOM as R
9−import React.Basic.Hooks (element)
13+import React.Basic.DOM.Events (targetValue)
14+import React.Basic.Events (handler)
15+import React.Basic.Hooks (ReactComponent, component, element, useState, (/\))
16+import React.Basic.Hooks as React
17+import Simple.JSON (readJSON_, writeJSON)
10−import Theme.Default (darkTheme)
18+import Theme.Default (darkTheme, lightTheme)
11import Theme.Provider (mkThemeProvider)
19import Theme.Provider (mkThemeProvider)
20+import Theme.Types (CSSTheme, fromTheme)
21+import Web.HTML (window)
22+import Web.HTML.Window (localStorage)
23+import Web.Storage.Storage (getItem, setItem)
12
24
13fullScreenDecorator ∷ JSX -> Effect JSX
25fullScreenDecorator ∷ JSX -> Effect JSX
14fullScreenDecorator child = do
26fullScreenDecorator child = do
27+ let
28+ dark = fromTheme darkTheme
29+ light = fromTheme lightTheme
30+ themeSwitcher <- mkThemeSwitcher
31+ pure
32+ $ R.div
33+ { style:
34+ css
35+ { width: "100vw"
36+ , minHeight: "900px"
37+ , minWidth: "1440px"
38+ , height: "100vh"
39+ }
40+ , children:
41+ [ element themeSwitcher
42+ { children: [ child ]
43+ , defaultTheme: { name: "Dark", theme: dark }
44+ , themes:
45+ [ { name: "Dark", theme: dark }
46+ , { name: "Light", theme: light }
47+ ]
48+ }
49+ ]
50+ }
51+
52+type ThemesWithNames
53+ = Map String CSSTheme
54+
55+type DefaultTheme = { name ∷ String, theme ∷ CSSTheme }
56+
57+mkThemeSwitcher ∷
58+ Effect
59+ ( ReactComponent { defaultTheme ∷ DefaultTheme, themes ∷ Array DefaultTheme, children ∷ Array JSX }
60+ )
61+mkThemeSwitcher = do
15− themeProvider <- mkThemeProvider
62+ themeProvider <- mkThemeProvider
63+ storage <- window >>= localStorage
64+ saved ∷ (Maybe DefaultTheme) <- getItem "theme" storage <#> (_ >>= readJSON_)
65+ component "ThemeSwitcher" \{ defaultTheme, themes, children } -> React.do
66+ { theme, name } /\ modTheme <- useState $ fromMaybe defaultTheme saved
67+ let
68+ setTheme newTheme = do
69+ setItem "theme" (writeJSON newTheme) storage
70+ modTheme (const newTheme)
71+ let
72+ handleClicked maybeValue =
73+ traverse_ setTheme do
74+ value <- maybeValue
75+ themes # find \x -> x.name == value
76+ let
77+ themeSelect =
78+ R.select
79+ { onChange: handler targetValue handleClicked
80+ , value: name
81+ , children:
82+ themes <#> \x ->
83+ R.option
84+ { value: x.name
85+ , key: x.name
86+ , children: [ R.text x.name ]
87+ }
88+ }
16 pure
89 pure
17− $ R.div
90+ $ element themeProvider
91+ { theme
18− { children:
92+ , children:
19− [ element themeProvider
93+ [ R.div
20− { theme: darkTheme
94+ { style: css { backgroundColor: theme.backgroundColour, width: "100%", height: "100%" }
21 , children:
95 , children:
22− [ R.div
96+ [ themeSelect ] <> children
23− { style:
24− css
25− { width: "100%"
26− , height: "100vh"
27− , backgroundColor: darkTheme.backgroundColour
28− }
29− , children:
30− [ R.div
31− { children:
32− [ child ]
33− , style:
34− css
35− { width: "500px"
36− , padding: "80px"
37− }
38− }
39− ]
40− }
41− ]
42 }
97 }
43 ]
98 ]
44 }
99 }
stories/ThemeStories.pursnew file+98
@@ -0,0 +1,98 @@
1+module ThemeStories where
2+
3+import Prelude hiding (add)
4+import Effect (Effect)
5+import React.Basic.DOM (css)
6+import React.Basic.DOM as R
7+import React.Basic.Hooks (component, element)
8+import Storybook.React (Storybook, add, storiesOf)
9+import Theme.Default (darkTheme, lightTheme)
10+import Theme.Types (fromTheme)
11+
12+stories ∷ Effect Storybook
13+stories =
14+ storiesOf "Theme" do
15+ add "The swatches in the themes" mkExample
16+ [ { theme: darkTheme, name: "Dark theme" }
17+ , { theme: lightTheme, name: "Light theme" }
18+ ]
19+ where
20+ mkExample = do
21+ swatch <- mkSwatch
22+ component "ExampleSwatches" \{ theme, name } -> React.do
23+ let
24+ cssTheme = fromTheme theme
25+
26+ sw name colour = element swatch { name, colour, fontFamily: cssTheme.textFontFamily }
27+ pure
28+ $ R.div
29+ { style:
30+ css
31+ { color: cssTheme.textColour
32+ , backgroundColor: cssTheme.backgroundColour
33+ }
34+ , children:
35+ [ R.div
36+ { style:
37+ css
38+ { fontSize: "2em"
39+ , fontFamily: cssTheme.headingFontFamily
40+ , padding: "20px 0 30px 10px"
41+ }
42+ , children: [ R.text name ]
43+ }
44+ , R.div
45+ { style:
46+ css
47+ { display: "grid"
48+ , gridTemplateColumns: "120px 120px 120px 120px 120px 120px"
49+ , gridRowGap: "20px"
50+ , paddingBottom: "20px"
51+ }
52+ , children:
53+ [ sw "IF Darkest" cssTheme.interfaceColourDarkest
54+ , sw "IF Darker" cssTheme.interfaceColourDarker
55+ , sw "Interface" cssTheme.interfaceColour
56+ , sw "IF Lighter" cssTheme.interfaceColourLighter
57+ , sw "IF Lightest" cssTheme.interfaceColourLightest
58+ , sw "Highlight" cssTheme.highlightColour
59+ , sw "TXT Darkest" cssTheme.textColourDarkest
60+ , sw "TXT Darker" cssTheme.textColourDarker
61+ , sw "TXT" cssTheme.textColour
62+ , sw "TXT Lighter" cssTheme.textColourLighter
63+ , sw "TXT Lightest" cssTheme.textColourLightest
64+ , sw "HighlightDK" cssTheme.highlightColourDark
65+ ]
66+ }
67+ ]
68+ }
69+
70+ mkSwatch = do
71+ component "Swatch" \{ name, colour, fontFamily } -> React.do
72+ pure
73+ $ R.div
74+ { style: css { display: "flex", flexDirection: "column", alignItems: "center" }
75+ , children:
76+ [ R.div
77+ { children: [ R.text name ]
78+ , style: css { fontFamily, paddingBottom: "5px" }
79+ }
80+ , R.div
81+ { style:
82+ css
83+ { background: colour
84+ , width: "100px"
85+ , height: "100px"
86+ , outline: "2px solid black"
87+ }
88+ }
89+ ]
90+ }
91+
92+loremIpsum ∷ String
93+loremIpsum =
94+ """PureScript is a strongly-typed, purely-functional programming language that compiles"""
95+ <> """ to JavaScript. It can be used to develop web applications, server side apps, and al"""
96+ <> """so desktop applications with use of Electron. Its syntax is mostly comparable to tha"""
97+ <> """t of Haskell. In addition, it introduces row polymorphism and extensible records.[2]"""
98+ <> """ Also, contrary to Haskell, PureScript adheres to a strict evaluation strategy."""
stories/TypographyStories.purs+3−11
@@ -4,16 +4,19 @@ import Prelude hiding (add)
4
4
5import Container.Component (mkContainer)
5import Container.Component (mkContainer)
6import Data.Maybe (Maybe(..))
6import Data.Maybe (Maybe(..))
7+import Decorator.FullScreen (fullScreenDecorator)
7import Effect (Effect)
8import Effect (Effect)
8import React.Basic (element)
9import React.Basic (element)
9import Storybook.React (Storybook, add, addDecorator, storiesOf)
10import Storybook.React (Storybook, add, addDecorator, storiesOf)
10import Theme.Default (darkTheme)
11import Theme.Default (darkTheme)
12+import Theme.Types (fromTheme)
11import Typography.Header (HeadingLevel(..), mkH)
13import Typography.Header (HeadingLevel(..), mkH)
12import Typography.Paragraph (mkP)
14import Typography.Paragraph (mkP)
13
15
14stories ∷ Effect Storybook
16stories ∷ Effect Storybook
15stories =
17stories =
16 storiesOf "Typography" do
18 storiesOf "Typography" do
19+ addDecorator fullScreenDecorator
17 add "All" mkH
20 add "All" mkH
18 [ { text: "A first level heading", level: H1, className: Nothing }
21 [ { text: "A first level heading", level: H1, className: Nothing }
19 , { text: "Second level", level: H2, className: Nothing }
22 , { text: "Second level", level: H2, className: Nothing }
@@ -21,17 +24,6 @@ stories =
21 , { text: "Finally, a pretty long h4 heading", level: H4, className: Nothing }
24 , { text: "Finally, a pretty long h4 heading", level: H4, className: Nothing }
22 , { text: "A subheading", level: Subheading, className: Nothing }
25 , { text: "A subheading", level: Subheading, className: Nothing }
23 ]
26 ]
24− addDecorator \jsx -> do
25− container <- mkContainer
26− p <- mkP
27− pure
28− $ element container
29− { theme: darkTheme
30− , children: [
31− jsx,
32− element p { text: loremIpsum }
33− ]
34− }
35 add "H1" mkH
27 add "H1" mkH
36 [ { text: "Purescript (H1)", level: H1, className: Nothing } ]
28 [ { text: "Purescript (H1)", level: H1, className: Nothing } ]
37 add "H2" mkH
29 add "H2" mkH