work work work
2
.gitignore
vendored
@ -34,6 +34,8 @@ playground/.spago
|
||||
|
||||
playground/src/Main.purs
|
||||
|
||||
blog/output
|
||||
|
||||
playgrounds/**
|
||||
!playgrounds/.gitkeep
|
||||
|
||||
|
BIN
assets/fonts/PragmataProLiga-Regular.woff
Normal file
BIN
assets/fonts/PragmataProLiga-Regular.woff2
Normal file
BIN
assets/fonts/Rubik-Bold.woff2
Normal file
BIN
assets/fonts/Rubik-BoldItalic.woff2
Normal file
BIN
assets/fonts/Rubik-Italic.woff2
Normal file
BIN
assets/fonts/Rubik-Light.woff2
Normal file
BIN
assets/fonts/Rubik-LightItalic.woff2
Normal file
BIN
assets/fonts/Rubik-Regular.woff2
Normal file
6
assets/fonts/fonts.css
Normal file
@ -0,0 +1,6 @@
|
||||
@font-face {
|
||||
font-family: "Rubik";
|
||||
src: url("Rubik-Regular.woff2") format("woff2");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
28
assets/icons/play.svg
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="90px" height="90px" viewBox="0 0 90 90" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 62 (91390) - https://sketch.com -->
|
||||
<title>Play</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs>
|
||||
<linearGradient x1="0%" y1="0%" x2="100%" y2="100%" id="linearGradient-1">
|
||||
<stop stop-color="#413F4E" stop-opacity="0.5" offset="0%"></stop>
|
||||
<stop stop-color="#101215" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="0%" y1="0%" x2="100%" y2="100%" id="linearGradient-2">
|
||||
<stop stop-color="#EF5BFF" offset="0%"></stop>
|
||||
<stop stop-color="#DB2FFF" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
<linearGradient x1="10.8727811%" y1="0%" x2="89.1272189%" y2="100%" id="linearGradient-3">
|
||||
<stop stop-color="#EF5BFF" offset="0%"></stop>
|
||||
<stop stop-color="#DB2FFF" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<rect id="Background" fill="#1F2228" x="-1064" y="-666" width="1600" height="2000"></rect>
|
||||
<rect id="Rectangle" fill="#14161A" x="-650" y="-28" width="888" height="549" rx="36"></rect>
|
||||
<g id="Play" stroke-width="3">
|
||||
<circle id="Oval" stroke="url(#linearGradient-2)" fill="url(#linearGradient-1)" cx="45" cy="45" r="43.5"></circle>
|
||||
<polygon id="Path" stroke="url(#linearGradient-3)" points="37 32 37 58 60 45"></polygon>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
6
blog/.eslintrc.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
globals: {
|
||||
__PATH_PREFIX__: true,
|
||||
},
|
||||
extends: `react-app`,
|
||||
}
|
72
blog/.gitignore
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Typescript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# gatsby files
|
||||
.cache/
|
||||
public
|
||||
|
||||
# Mac files
|
||||
.DS_Store
|
||||
|
||||
# Yarn
|
||||
yarn-error.log
|
||||
.pnp/
|
||||
.pnp.js
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# Purescript
|
||||
.spago/
|
22
blog/LICENSE
Normal file
@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 gatsbyjs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
27
blog/README.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Gatsby Starter MDX Basic
|
||||
|
||||
View this starter [live on Netlify](https://gatsby-starter-mdx-basic.netlify.com/)
|
||||
|
||||
This starter build MDX support into the
|
||||
[gatsby-default-starter](https://github.com/gatsbyjs/gatsby-starter-default). Its
|
||||
README also applies here.
|
||||
|
||||
1. Create a new Gatsby site using this starter
|
||||
|
||||
```sh
|
||||
gatsby new my-site https://github.com/ChristopherBiscardi/gatsby-starter-mdx-basic
|
||||
```
|
||||
|
||||
2. Install dependencies
|
||||
|
||||
```sh
|
||||
yarn
|
||||
```
|
||||
|
||||
3. Run the develop script
|
||||
|
||||
```sh
|
||||
yarn develop
|
||||
```
|
||||
|
||||
4. Edit Page 2 in `src/pages/page-2.mdx`
|
81
blog/gatsby-config.js
Normal file
@ -0,0 +1,81 @@
|
||||
const path = require("path");
|
||||
var proxy = require("http-proxy-middleware")
|
||||
|
||||
module.exports = {
|
||||
siteMetadata: {
|
||||
title: "Gatsby Starter MDX Basic",
|
||||
description:
|
||||
"Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.",
|
||||
author: "@chrisbiscardi"
|
||||
},
|
||||
developMiddleware: app => {
|
||||
app.use(
|
||||
"/api", proxy({
|
||||
target: "http://127.0.0.1:14188",
|
||||
pathRewrite: {
|
||||
"/api": "",
|
||||
}
|
||||
})
|
||||
)
|
||||
},
|
||||
plugins: [
|
||||
{
|
||||
resolve: `gatsby-plugin-mdx`,
|
||||
options: {
|
||||
defaultLayouts: { default: path.resolve("./src/components/layout.js") }
|
||||
}
|
||||
},
|
||||
{
|
||||
resolve: "gatsby-plugin-web-font-loader",
|
||||
options: {
|
||||
custom: {
|
||||
families: ["Rubik"],
|
||||
urls: ["/fonts/fonts.css"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-plugin-alias-imports`,
|
||||
options: {
|
||||
alias: {
|
||||
react: path.resolve("./node_modules/react"),
|
||||
"react-dom": path.resolve("./node_modules/react-dom")
|
||||
},
|
||||
extensions: []
|
||||
}
|
||||
},
|
||||
"gatsby-plugin-react-helmet",
|
||||
{
|
||||
resolve: `gatsby-source-filesystem`,
|
||||
options: {
|
||||
name: `images`,
|
||||
path: `${__dirname}/src/images`
|
||||
}
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-source-filesystem`,
|
||||
options: {
|
||||
name: `pages`,
|
||||
path: `${__dirname}/src/pages`
|
||||
}
|
||||
},
|
||||
"gatsby-plugin-purescript",
|
||||
"gatsby-transformer-sharp",
|
||||
"gatsby-plugin-sharp",
|
||||
{
|
||||
resolve: `gatsby-plugin-manifest`,
|
||||
options: {
|
||||
name: "gatsby-default-mdx-basic",
|
||||
short_name: "starter",
|
||||
start_url: "/",
|
||||
background_color: "#663399",
|
||||
theme_color: "#663399",
|
||||
display: "minimal-ui",
|
||||
icon: "src/images/gatsby-icon.png" // This path is relative to the root of the site.
|
||||
}
|
||||
}
|
||||
// this (optional) plugin enables Progressive Web App + Offline functionality
|
||||
// To learn more, visit: https://gatsby.app/offline
|
||||
// 'gatsby-plugin-offline',
|
||||
]
|
||||
};
|
8
blog/gatsby-node.js
Normal file
@ -0,0 +1,8 @@
|
||||
const MonacoWebpackPlugin = require(`monaco-editor-webpack-plugin`);
|
||||
exports.onCreateWebpackConfig = ({ actions }) => {
|
||||
actions.setWebpackConfig({
|
||||
plugins: [
|
||||
new MonacoWebpackPlugin()
|
||||
]
|
||||
});
|
||||
};
|
18288
blog/package-lock.json
generated
Normal file
49
blog/package.json
Normal file
@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "gatsby-starter-mdx-basic",
|
||||
"description": "Gatsby starter MDX basic",
|
||||
"version": "1.0.0",
|
||||
"author": "Chris Biscardi <chris@christopherbiscardi.com>",
|
||||
"dependencies": {
|
||||
"@mdx-js/mdx": "^1.1.5",
|
||||
"@mdx-js/react": "^1.1.5",
|
||||
"@monaco-editor/react": "^3.1.0",
|
||||
"gatsby": "^2.13.50",
|
||||
"gatsby-image": "^2.2.8",
|
||||
"gatsby-plugin-alias-imports": "^1.0.5",
|
||||
"gatsby-plugin-manifest": "^2.2.4",
|
||||
"gatsby-plugin-mdx": "^1.0.0",
|
||||
"gatsby-plugin-offline": "^2.2.4",
|
||||
"gatsby-plugin-purescript": "^2.0.0",
|
||||
"gatsby-plugin-react-helmet": "^3.1.3",
|
||||
"gatsby-plugin-sharp": "^2.2.9",
|
||||
"gatsby-plugin-web-font-loader": "^1.0.4",
|
||||
"gatsby-source-filesystem": "^2.1.8",
|
||||
"gatsby-transformer-sharp": "^2.2.5",
|
||||
"mdx-utils": "^0.2.0",
|
||||
"monaco-editor": "^0.20.0",
|
||||
"monaco-editor-webpack-plugin": "^1.8.2",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6",
|
||||
"react-helmet": "^5.2.1",
|
||||
"react-monaco-editor": "^0.33.0"
|
||||
},
|
||||
"keywords": [
|
||||
"gatsby"
|
||||
],
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "gatsby build",
|
||||
"develop": "gatsby develop",
|
||||
"start": "npm run develop",
|
||||
"format": "prettier --write \"src/**/*.js\"",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "^1.18.2"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/christopherbiscardi/gatsby-starter-mdx-basic"
|
||||
}
|
||||
}
|
168
blog/packages.dhall
Normal file
@ -0,0 +1,168 @@
|
||||
{-
|
||||
Welcome to your new Dhall package-set!
|
||||
|
||||
Below are instructions for how to edit this file for most use
|
||||
cases, so that you don't need to know Dhall to use it.
|
||||
|
||||
## Warning: Don't Move This Top-Level Comment!
|
||||
|
||||
Due to how `dhall format` currently works, this comment's
|
||||
instructions cannot appear near corresponding sections below
|
||||
because `dhall format` will delete the comment. However,
|
||||
it will not delete a top-level comment like this one.
|
||||
|
||||
## Use Cases
|
||||
|
||||
Most will want to do one or both of these options:
|
||||
1. Override/Patch a package's dependency
|
||||
2. Add a package not already in the default package set
|
||||
|
||||
This file will continue to work whether you use one or both options.
|
||||
Instructions for each option are explained below.
|
||||
|
||||
### Overriding/Patching a package
|
||||
|
||||
Purpose:
|
||||
- Change a package's dependency to a newer/older release than the
|
||||
default package set's release
|
||||
- Use your own modified version of some dependency that may
|
||||
include new API, changed API, removed API by
|
||||
using your custom git repo of the library rather than
|
||||
the package set's repo
|
||||
|
||||
Syntax:
|
||||
Replace the overrides' "{=}" (an empty record) with the following idea
|
||||
The "//" or "⫽" means "merge these two records and
|
||||
when they have the same value, use the one on the right:"
|
||||
-------------------------------
|
||||
let override =
|
||||
{ packageName =
|
||||
upstream.packageName // { updateEntity1 = "new value", updateEntity2 = "new value" }
|
||||
, packageName =
|
||||
upstream.packageName // { version = "v4.0.0" }
|
||||
, packageName =
|
||||
upstream.packageName // { repo = "https://www.example.com/path/to/new/repo.git" }
|
||||
}
|
||||
-------------------------------
|
||||
|
||||
Example:
|
||||
-------------------------------
|
||||
let overrides =
|
||||
{ halogen =
|
||||
upstream.halogen // { version = "master" }
|
||||
, halogen-vdom =
|
||||
upstream.halogen-vdom // { version = "v4.0.0" }
|
||||
}
|
||||
-------------------------------
|
||||
|
||||
### Additions
|
||||
|
||||
Purpose:
|
||||
- Add packages that aren't already included in the default package set
|
||||
|
||||
Syntax:
|
||||
Replace the additions' "{=}" (an empty record) with the following idea:
|
||||
-------------------------------
|
||||
let additions =
|
||||
{ "package-name" =
|
||||
{ dependencies =
|
||||
[ "dependency1"
|
||||
, "dependency2"
|
||||
]
|
||||
, repo =
|
||||
"https://example.com/path/to/git/repo.git"
|
||||
, version =
|
||||
"tag ('v4.0.0') or branch ('master')"
|
||||
}
|
||||
, "package-name" =
|
||||
{ dependencies =
|
||||
[ "dependency1"
|
||||
, "dependency2"
|
||||
]
|
||||
, repo =
|
||||
"https://example.com/path/to/git/repo.git"
|
||||
, version =
|
||||
"tag ('v4.0.0') or branch ('master')"
|
||||
}
|
||||
, etc.
|
||||
}
|
||||
-------------------------------
|
||||
|
||||
Example:
|
||||
-------------------------------
|
||||
let additions =
|
||||
{ benchotron =
|
||||
{ dependencies =
|
||||
[ "arrays"
|
||||
, "exists"
|
||||
, "profunctor"
|
||||
, "strings"
|
||||
, "quickcheck"
|
||||
, "lcg"
|
||||
, "transformers"
|
||||
, "foldable-traversable"
|
||||
, "exceptions"
|
||||
, "node-fs"
|
||||
, "node-buffer"
|
||||
, "node-readline"
|
||||
, "datetime"
|
||||
, "now"
|
||||
],
|
||||
, repo =
|
||||
"https://github.com/hdgarrood/purescript-benchotron.git"
|
||||
, version =
|
||||
"v7.0.0"
|
||||
}
|
||||
}
|
||||
-------------------------------
|
||||
-}
|
||||
|
||||
|
||||
let upstream =
|
||||
https://github.com/purescript/package-sets/releases/download/psc-0.13.6-20200123/packages.dhall sha256:687bb9a2d38f2026a89772c47390d02939340b01e31aaa22de9247eadd64af05
|
||||
|
||||
let overrides = {=}
|
||||
|
||||
let additions =
|
||||
{ react-testing-library =
|
||||
{ dependencies =
|
||||
[ "aff-promise"
|
||||
, "console"
|
||||
, "debug"
|
||||
, "effect"
|
||||
, "foreign"
|
||||
, "foreign-object"
|
||||
, "psci-support"
|
||||
, "react-basic-hooks"
|
||||
, "remotedata"
|
||||
, "run"
|
||||
, "simple-json"
|
||||
, "spec"
|
||||
, "spec-discovery"
|
||||
]
|
||||
, repo =
|
||||
"https://github.com/i-am-the-slime/purescript-react-testing-library.git"
|
||||
, version = "b872928414a887ccefbe857038af4e57227dad16"
|
||||
}
|
||||
, pseudo-random =
|
||||
{ dependencies =
|
||||
[ "prelude", "console", "effect", "lcg", "arrays", "st" ]
|
||||
, repo = "https://github.com/opyapeus/purescript-pseudo-random.git"
|
||||
, version = "7715e8a2c096c480a093a5e0a6df1ece4df5ed2a"
|
||||
}
|
||||
, matryoshka =
|
||||
{ dependencies =
|
||||
[ "prelude", "fixed-points", "free", "transformers", "profunctor" ]
|
||||
, repo = "https://github.com/slamdata/purescript-matryoshka.git"
|
||||
, version = "caaca2d836d52159ba7963333996286a00428394"
|
||||
}
|
||||
, interpolate =
|
||||
{ dependencies = [ "prelude" ]
|
||||
, repo =
|
||||
"https://github.com/jordanmartinez/purescript-interpolate.git"
|
||||
, version = "v2.0.1"
|
||||
}
|
||||
, yoga-components = ../components/spago.dhall as Location
|
||||
}
|
||||
|
||||
in upstream ⫽ overrides ⫽ additions
|
9
blog/spago.dhall
Normal file
@ -0,0 +1,9 @@
|
||||
{-
|
||||
Welcome to a Spago project!
|
||||
You can edit this file as you like.
|
||||
-}
|
||||
{ name = "my-project"
|
||||
, dependencies = [ "console", "effect", "psci-support", "yoga-components" ]
|
||||
, packages = ./packages.dhall
|
||||
, sources = [ "src/**/*.purs", "test/**/*.purs" ]
|
||||
}
|
41
blog/src/components/YogaCard.purs
Normal file
@ -0,0 +1,41 @@
|
||||
module YogaCard where
|
||||
|
||||
import Card.Component (mkCard)
|
||||
import CompileEditor.Component (mkCompileEditor)
|
||||
import Effect (Effect)
|
||||
import Milkis.Impl (FetchImpl)
|
||||
import React.Basic (JSX, ReactComponent)
|
||||
import Theme (fromTheme)
|
||||
import Theme.Default (darkTheme)
|
||||
import Theme.Provider (mkThemeProvider)
|
||||
import Theme.Types (CSSTheme)
|
||||
|
||||
makeCard ∷
|
||||
Effect
|
||||
( ReactComponent
|
||||
{ className ∷ String
|
||||
, kids ∷ Array JSX
|
||||
}
|
||||
)
|
||||
makeCard = mkCard
|
||||
|
||||
mkEditor ∷
|
||||
FetchImpl ->
|
||||
Effect
|
||||
( ReactComponent
|
||||
{ height ∷ String
|
||||
, initialCode ∷ String
|
||||
}
|
||||
)
|
||||
mkEditor = mkCompileEditor
|
||||
|
||||
makeThemeProvider :: Effect
|
||||
(ReactComponent
|
||||
{ children :: Array JSX
|
||||
, theme :: CSSTheme
|
||||
}
|
||||
)
|
||||
makeThemeProvider = mkThemeProvider
|
||||
|
||||
dark :: CSSTheme
|
||||
dark = fromTheme darkTheme
|
20
blog/src/components/code.js
Normal file
@ -0,0 +1,20 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
const yogaCard = require("./YogaCard.purs");
|
||||
const fetch = typeof window !== "undefined" && window.fetch;
|
||||
|
||||
const Code = ({ codeString, language, ...props }) => {
|
||||
const [Editor, setEditor] = useState(null);
|
||||
console.log("stuff", props);
|
||||
useEffect(() => {
|
||||
if (Editor === null) {
|
||||
const Eddy = yogaCard.mkEditor(fetch)();
|
||||
setEditor(prev => console.log("Prev", prev) || Eddy);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
Editor !== null ? <Editor height="300px" initialCode={codeString}></Editor> : ""
|
||||
);
|
||||
};
|
||||
|
||||
export default Code;
|
15
blog/src/components/header.js
Normal file
@ -0,0 +1,15 @@
|
||||
import { Link } from "gatsby";
|
||||
import PropTypes from "prop-types";
|
||||
import React from "react";
|
||||
|
||||
const Header = ({ siteTitle }) => <div>{siteTitle}</div>;
|
||||
|
||||
Header.propTypes = {
|
||||
siteTitle: PropTypes.string
|
||||
};
|
||||
|
||||
Header.defaultProps = {
|
||||
siteTitle: ""
|
||||
};
|
||||
|
||||
export default Header;
|
32
blog/src/components/image.js
Normal file
@ -0,0 +1,32 @@
|
||||
import React from 'react'
|
||||
import { StaticQuery, graphql } from 'gatsby'
|
||||
import Img from 'gatsby-image'
|
||||
|
||||
/*
|
||||
* This component is built using `gatsby-image` to automatically serve optimized
|
||||
* images with lazy loading and reduced file sizes. The image is loaded using a
|
||||
* `StaticQuery`, which allows us to load the image from directly within this
|
||||
* component, rather than having to pass the image data down from pages.
|
||||
*
|
||||
* For more information, see the docs:
|
||||
* - `gatsby-image`: https://gatsby.app/gatsby-image
|
||||
* - `StaticQuery`: https://gatsby.app/staticquery
|
||||
*/
|
||||
|
||||
const Image = () => (
|
||||
<StaticQuery
|
||||
query={graphql`
|
||||
query {
|
||||
placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
|
||||
childImageSharp {
|
||||
fluid(maxWidth: 300) {
|
||||
...GatsbyImageSharpFluid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`}
|
||||
render={data => <Img fluid={data.placeholderImage.childImageSharp.fluid} />}
|
||||
/>
|
||||
)
|
||||
export default Image
|
48
blog/src/components/layout.js
Normal file
@ -0,0 +1,48 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { StaticQuery, graphql } from "gatsby";
|
||||
import { MDXProvider } from "@mdx-js/react";
|
||||
import { preToCodeBlock } from "mdx-utils";
|
||||
const yogaCard = require("./YogaCard.purs");
|
||||
|
||||
import Header from "./header";
|
||||
import Code from "./code";
|
||||
|
||||
const mdxProviderComponents = {
|
||||
pre: preProps => {
|
||||
const props = preToCodeBlock(preProps);
|
||||
return props ? <Code {...props} /> : <pre {...preProps} />;
|
||||
}
|
||||
};
|
||||
|
||||
const ThemeProvider = yogaCard.makeThemeProvider();
|
||||
|
||||
const Layout = ({ children }) => (
|
||||
<ThemeProvider theme={yogaCard.dark}>
|
||||
<MDXProvider components={mdxProviderComponents}>
|
||||
<StaticQuery
|
||||
query={graphql`
|
||||
query SiteTitleQuery {
|
||||
site {
|
||||
siteMetadata {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
`}
|
||||
render={data => (
|
||||
<div style={{backgroundColor: yogaCard.dark.backgroundColour}}>
|
||||
<Header siteTitle={data.site.siteMetadata.title} />
|
||||
<div>{children}</div>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</MDXProvider>
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
||||
Layout.propTypes = {
|
||||
children: PropTypes.node.isRequired
|
||||
};
|
||||
|
||||
export default Layout;
|
96
blog/src/components/seo.js
Normal file
@ -0,0 +1,96 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Helmet from 'react-helmet'
|
||||
import { StaticQuery, graphql } from 'gatsby'
|
||||
|
||||
function SEO({ description, lang, meta, keywords, title }) {
|
||||
return (
|
||||
<StaticQuery
|
||||
query={detailsQuery}
|
||||
render={data => {
|
||||
const metaDescription =
|
||||
description || data.site.siteMetadata.description
|
||||
return (
|
||||
<Helmet
|
||||
htmlAttributes={{
|
||||
lang,
|
||||
}}
|
||||
title={title}
|
||||
titleTemplate={`%s | ${data.site.siteMetadata.title}`}
|
||||
meta={[
|
||||
{
|
||||
name: 'description',
|
||||
content: metaDescription,
|
||||
},
|
||||
{
|
||||
property: 'og:title',
|
||||
content: title,
|
||||
},
|
||||
{
|
||||
property: 'og:description',
|
||||
content: metaDescription,
|
||||
},
|
||||
{
|
||||
property: 'og:type',
|
||||
content: 'website',
|
||||
},
|
||||
{
|
||||
name: 'twitter:card',
|
||||
content: 'summary',
|
||||
},
|
||||
{
|
||||
name: 'twitter:creator',
|
||||
content: data.site.siteMetadata.author,
|
||||
},
|
||||
{
|
||||
name: 'twitter:title',
|
||||
content: title,
|
||||
},
|
||||
{
|
||||
name: 'twitter:description',
|
||||
content: metaDescription,
|
||||
},
|
||||
]
|
||||
.concat(
|
||||
keywords.length > 0
|
||||
? {
|
||||
name: 'keywords',
|
||||
content: keywords.join(', '),
|
||||
}
|
||||
: []
|
||||
)
|
||||
.concat(meta)}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
SEO.defaultProps = {
|
||||
lang: 'en',
|
||||
meta: [],
|
||||
keywords: [],
|
||||
}
|
||||
|
||||
SEO.propTypes = {
|
||||
description: PropTypes.string,
|
||||
lang: PropTypes.string,
|
||||
meta: PropTypes.array,
|
||||
keywords: PropTypes.arrayOf(PropTypes.string),
|
||||
title: PropTypes.string.isRequired,
|
||||
}
|
||||
|
||||
export default SEO
|
||||
|
||||
const detailsQuery = graphql`
|
||||
query DefaultSEOQuery {
|
||||
site {
|
||||
siteMetadata {
|
||||
title
|
||||
description
|
||||
author
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
BIN
blog/src/images/gatsby-astronaut.png
Normal file
After Width: | Height: | Size: 163 KiB |
BIN
blog/src/images/gatsby-icon.png
Normal file
After Width: | Height: | Size: 21 KiB |
14
blog/src/pages/404.js
Normal file
@ -0,0 +1,14 @@
|
||||
import React from 'react'
|
||||
|
||||
import Layout from '../components/layout'
|
||||
import SEO from '../components/seo'
|
||||
|
||||
const NotFoundPage = () => (
|
||||
<Layout>
|
||||
<SEO title="404: Not found" />
|
||||
<h1>NOT FOUND</h1>
|
||||
<p>You just hit a route that doesn't exist... the sadness.</p>
|
||||
</Layout>
|
||||
)
|
||||
|
||||
export default NotFoundPage
|
27
blog/src/pages/index.mdx
Normal file
@ -0,0 +1,27 @@
|
||||
import { Link } from 'gatsby'
|
||||
|
||||
import Layout from '../components/layout'
|
||||
import Image from '../components/image'
|
||||
import SEO from '../components/seo'
|
||||
|
||||
<SEO title="Home" keywords={['gatsby', 'application', 'react']} />
|
||||
|
||||
```purescript
|
||||
module Main where
|
||||
import Batteries
|
||||
|
||||
main :: Effect Unit
|
||||
main = log "Hello!"
|
||||
```
|
||||
|
||||
# Hi people
|
||||
|
||||
Welcome to your new Gatsby site.
|
||||
|
||||
Now go build something great.
|
||||
|
||||
<div style={{ maxWidth: '300px', marginBottom: '1.45rem' }}>
|
||||
<Image />
|
||||
</div>
|
||||
<Link to="/page-2/">Go to page 2</Link>
|
||||
|
11
blog/src/pages/page-2.mdx
Normal file
@ -0,0 +1,11 @@
|
||||
import { Link } from 'gatsby'
|
||||
import Layout from '../components/layout'
|
||||
import SEO from '../components/seo'
|
||||
|
||||
<SEO title="Page two" />
|
||||
|
||||
# Hi from the second page
|
||||
|
||||
Welcome to page 2
|
||||
|
||||
<Link to="/">Go back to the homepage</Link>
|
1
blog/static/fonts
Symbolic link
@ -0,0 +1 @@
|
||||
../../assets/fonts
|
11
blog/test/Main.purs
Normal file
@ -0,0 +1,11 @@
|
||||
module Test.Main where
|
||||
|
||||
import Prelude
|
||||
|
||||
import Effect (Effect)
|
||||
import Effect.Class.Console (log)
|
||||
|
||||
main :: Effect Unit
|
||||
main = do
|
||||
log "🍝"
|
||||
log "You should add some tests."
|
@ -1,6 +1,6 @@
|
||||
import { configure, forceReRender } from "@storybook/react";
|
||||
|
||||
const req = require.context("../stories/", true, /Stories\.purs$/);
|
||||
const req = require.context("../src/", true, /Stories\.purs$/);
|
||||
|
||||
function loadStories() {
|
||||
req.keys().forEach(filename => {
|
||||
|
@ -1,176 +0,0 @@
|
||||
{-
|
||||
Welcome to your new Dhall package-set!
|
||||
|
||||
Below are instructions for how to edit this file for most use
|
||||
cases, so that you don't need to know Dhall to use it.
|
||||
|
||||
## Warning: Don't Move This Top-Level Comment!
|
||||
|
||||
Due to how `dhall format` currently works, this comment's
|
||||
instructions cannot appear near corresponding sections below
|
||||
because `dhall format` will delete the comment. However,
|
||||
it will not delete a top-level comment like this one.
|
||||
|
||||
## Use Cases
|
||||
|
||||
Most will want to do one or both of these options:
|
||||
1. Override/Patch a package's dependency
|
||||
2. Add a package not already in the default package set
|
||||
|
||||
This file will continue to work whether you use one or both options.
|
||||
Instructions for each option are explained below.
|
||||
|
||||
### Overriding/Patching a package
|
||||
|
||||
Purpose:
|
||||
- Change a package's dependency to a newer/older release than the
|
||||
default package set's release
|
||||
- Use your own modified version of some dependency that may
|
||||
include new API, changed API, removed API by
|
||||
using your custom git repo of the library rather than
|
||||
the package set's repo
|
||||
|
||||
Syntax:
|
||||
Replace the overrides' "{=}" (an empty record) with the following idea
|
||||
The "//" or "⫽" means "merge these two records and
|
||||
when they have the same value, use the one on the right:"
|
||||
-------------------------------
|
||||
let override =
|
||||
{ packageName =
|
||||
upstream.packageName // { updateEntity1 = "new value", updateEntity2 = "new value" }
|
||||
, packageName =
|
||||
upstream.packageName // { version = "v4.0.0" }
|
||||
, packageName =
|
||||
upstream.packageName // { repo = "https://www.example.com/path/to/new/repo.git" }
|
||||
}
|
||||
-------------------------------
|
||||
|
||||
Example:
|
||||
-------------------------------
|
||||
let overrides =
|
||||
{ halogen =
|
||||
upstream.halogen // { version = "master" }
|
||||
, halogen-vdom =
|
||||
upstream.halogen-vdom // { version = "v4.0.0" }
|
||||
}
|
||||
-------------------------------
|
||||
|
||||
### Additions
|
||||
|
||||
Purpose:
|
||||
- Add packages that aren't already included in the default package set
|
||||
|
||||
Syntax:
|
||||
Replace the additions' "{=}" (an empty record) with the following idea:
|
||||
-------------------------------
|
||||
let additions =
|
||||
{ "package-name" =
|
||||
{ dependencies =
|
||||
[ "dependency1"
|
||||
, "dependency2"
|
||||
]
|
||||
, repo =
|
||||
"https://example.com/path/to/git/repo.git"
|
||||
, version =
|
||||
"tag ('v4.0.0') or branch ('master')"
|
||||
}
|
||||
, "package-name" =
|
||||
{ dependencies =
|
||||
[ "dependency1"
|
||||
, "dependency2"
|
||||
]
|
||||
, repo =
|
||||
"https://example.com/path/to/git/repo.git"
|
||||
, version =
|
||||
"tag ('v4.0.0') or branch ('master')"
|
||||
}
|
||||
, etc.
|
||||
}
|
||||
-------------------------------
|
||||
|
||||
Example:
|
||||
-------------------------------
|
||||
let additions =
|
||||
{ benchotron =
|
||||
{ dependencies =
|
||||
[ "arrays"
|
||||
, "exists"
|
||||
, "profunctor"
|
||||
, "strings"
|
||||
, "quickcheck"
|
||||
, "lcg"
|
||||
, "transformers"
|
||||
, "foldable-traversable"
|
||||
, "exceptions"
|
||||
, "node-fs"
|
||||
, "node-buffer"
|
||||
, "node-readline"
|
||||
, "datetime"
|
||||
, "now"
|
||||
],
|
||||
, repo =
|
||||
"https://github.com/hdgarrood/purescript-benchotron.git"
|
||||
, version =
|
||||
"v7.0.0"
|
||||
}
|
||||
}
|
||||
-------------------------------
|
||||
-}
|
||||
|
||||
|
||||
let upstream =
|
||||
https://github.com/purescript/package-sets/releases/download/psc-0.13.3-20190920/packages.dhall sha256:53873cf2fc4a343a41f335ee47c1706ecf755ac7c5a336e8eb03ad23165dfd28
|
||||
|
||||
let overrides = {=}
|
||||
-- { react-basic-hooks =
|
||||
-- upstream.react-basic-hooks // { version = "v2.0.1" }
|
||||
-- , spec-discovery =
|
||||
-- upstream.spec-discovery // { version = "1ca3416e6c0729eca8d5204f22cf0aa09c98df9d" }
|
||||
-- , react-basic =
|
||||
-- upstream.react-basic
|
||||
-- // { repo =
|
||||
-- "https://github.com/i-am-the-slime/purescript-react-basic"
|
||||
-- , version =
|
||||
-- "dda3f711d84cd5dc1817a71ff01f0426b04ed791"
|
||||
-- }
|
||||
-- }
|
||||
|
||||
let additions =
|
||||
{ react-testing-library =
|
||||
{ dependencies =
|
||||
[ "aff-promise"
|
||||
, "console"
|
||||
, "debug"
|
||||
, "effect"
|
||||
, "foreign"
|
||||
, "foreign-object"
|
||||
, "psci-support"
|
||||
, "react-basic-hooks"
|
||||
, "remotedata"
|
||||
, "run"
|
||||
, "simple-json"
|
||||
, "spec"
|
||||
, "spec-discovery"
|
||||
]
|
||||
, repo =
|
||||
"https://github.com/i-am-the-slime/purescript-react-testing-library.git"
|
||||
, version =
|
||||
"b872928414a887ccefbe857038af4e57227dad16"
|
||||
}
|
||||
, pseudo-random =
|
||||
{ dependencies =
|
||||
[ "prelude"
|
||||
, "console"
|
||||
, "effect"
|
||||
, "lcg"
|
||||
, "arrays"
|
||||
, "st"
|
||||
]
|
||||
, repo =
|
||||
"https://github.com/opyapeus/purescript-pseudo-random.git"
|
||||
, version =
|
||||
"7715e8a2c096c480a093a5e0a6df1ece4df5ed2a"
|
||||
}
|
||||
}
|
||||
|
||||
in upstream // overrides // additions
|
1
client/packages.dhall
Symbolic link
@ -0,0 +1 @@
|
||||
../packages.dhall
|
@ -2,13 +2,13 @@
|
||||
Welcome to a Spago project!
|
||||
You can edit this file as you like.
|
||||
-}
|
||||
{ name =
|
||||
"my-project"
|
||||
{ name = "my-project"
|
||||
, dependencies =
|
||||
[ "console"
|
||||
, "css"
|
||||
, "debug"
|
||||
, "effect"
|
||||
, "interpolate"
|
||||
, "milkis"
|
||||
, "psci-support"
|
||||
, "pseudo-random"
|
||||
@ -20,8 +20,6 @@ You can edit this file as you like.
|
||||
, "string-parsers"
|
||||
, "web-html"
|
||||
]
|
||||
, packages =
|
||||
./packages.dhall
|
||||
, sources =
|
||||
[ "src/**/*.purs", "test/**/*.purs" ]
|
||||
, packages = ./packages.dhall
|
||||
, sources = [ "src/**/*.purs", "test/**/*.purs" ]
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import Container.Landing (mkLandingPage)
|
||||
import Container.Sidebar (mkSidebar, mkSidebarLink)
|
||||
import Data.Nullable as Nullable
|
||||
import Effect (Effect)
|
||||
import Milkis.Impl.Window (windowFetch)
|
||||
import Polyfill.SmoothScrolling (smoothScrollPolyfill)
|
||||
import React.Basic (JSX)
|
||||
import React.Basic.DOM as R
|
||||
@ -53,6 +54,7 @@ mkContainerContent = do
|
||||
, padding: "20px"
|
||||
, minHeight: "calc(100vh - 40px)"
|
||||
, paddingLeft: "100px"
|
||||
, zIndex: 0
|
||||
}
|
||||
, icon: cssSafer { fill: "theme.textColour" }
|
||||
}
|
||||
@ -60,7 +62,7 @@ mkContainerContent = do
|
||||
sidebar <- mkSidebar
|
||||
header <- mkHeader
|
||||
sidebarLink <- mkSidebarLink
|
||||
editor <- mkCompileEditor
|
||||
editor <- mkCompileEditor windowFetch
|
||||
component "ContainerContent" \{ kids } -> React.do
|
||||
classes <- useStyles
|
||||
collapsed /\ modifyCollapsed <- useState true
|
||||
@ -73,7 +75,7 @@ mkContainerContent = do
|
||||
, element sidebar
|
||||
{ collapsed
|
||||
, modifyCollapsed
|
||||
, children:
|
||||
, kids:
|
||||
[ element sidebarLink { name: "Learn", icon: element appendIcon {}, collapsed }
|
||||
, element sidebarLink { name: "Try", icon: element bindIcon {}, collapsed }
|
||||
, element sidebarLink { name: "Share", icon: element applyflippedIcon {}, collapsed }
|
||||
@ -94,4 +96,4 @@ initialCode =
|
||||
import Batteries
|
||||
|
||||
main :: Effect Unit
|
||||
main ="""
|
||||
main = log "Let's do this!""""
|
||||
|
@ -70,8 +70,13 @@ mkLandingPage = do
|
||||
}
|
||||
, actionButton:
|
||||
cssSafer
|
||||
{ fontSize: "40pt"
|
||||
, marginLeft: "5vw"
|
||||
{ marginLeft: "5vw"
|
||||
, display: "flex"
|
||||
}
|
||||
, actualActionButton:
|
||||
cssSafer
|
||||
{ paddingLeft: "10px"
|
||||
, paddingRight: "10px"
|
||||
}
|
||||
, landingImage:
|
||||
cssSafer
|
||||
@ -119,7 +124,7 @@ mkLandingPage = do
|
||||
}
|
||||
, buttonType: HighlightedButton
|
||||
, kids: [ R.text buttonText ]
|
||||
, className: ""
|
||||
, className: classes.actualActionButton
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ import Theme.Types (CSSTheme)
|
||||
mkSidebar ∷
|
||||
Effect
|
||||
( ReactComponent
|
||||
{ children ∷ Array JSX
|
||||
{ kids ∷ Array JSX
|
||||
, modifyCollapsed ∷ (Boolean -> Boolean) -> Effect Unit
|
||||
, collapsed ∷ Boolean
|
||||
}
|
||||
@ -60,7 +60,7 @@ mkSidebar = do
|
||||
{} -- transform: "rotate(180deg)"}
|
||||
}
|
||||
menu <- mkMenu
|
||||
component "Sidebar" \{ children, collapsed, modifyCollapsed } -> React.do
|
||||
component "Sidebar" \{ kids, collapsed, modifyCollapsed } -> React.do
|
||||
rawClasses <- useStyles
|
||||
let
|
||||
classes = flip classNames rawClasses
|
||||
@ -81,7 +81,7 @@ mkSidebar = do
|
||||
]
|
||||
}
|
||||
]
|
||||
<> children
|
||||
<> kids
|
||||
}
|
||||
|
||||
mkSidebarLink ∷ Effect (ReactComponent { name ∷ String, icon ∷ JSX, collapsed ∷ Boolean })
|
||||
|
@ -1,4 +1,4 @@
|
||||
module ContainerStories where
|
||||
module Container.Stories where
|
||||
|
||||
import Prelude hiding (add)
|
||||
import Container.Component (mkContainer)
|
@ -23,6 +23,9 @@ import Theme.Types (CSSTheme)
|
||||
import Web.HTML (window)
|
||||
import Web.HTML.Window (localStorage)
|
||||
import Web.Storage.Storage (getItem, setItem)
|
||||
import Yoga.Font as Font
|
||||
import Yoga.Font.PragmataPro as PragmataPro
|
||||
import Yoga.Font.Rubik as Rubik
|
||||
|
||||
fullScreenDecorator ∷ Effect JSX -> Effect JSX
|
||||
fullScreenDecorator mkChild = do
|
||||
@ -41,7 +44,7 @@ fullScreenDecorator mkChild = do
|
||||
}
|
||||
, children:
|
||||
[ element themeSwitcher
|
||||
{ children: [ child ]
|
||||
{ kids: [ child ]
|
||||
, defaultTheme: { name: "Dark", theme: dark }
|
||||
, themes:
|
||||
[ { name: "Dark", theme: dark }
|
||||
@ -59,7 +62,7 @@ type DefaultTheme
|
||||
|
||||
mkThemeSwitcher ∷
|
||||
Effect
|
||||
( ReactComponent { defaultTheme ∷ DefaultTheme, themes ∷ Array DefaultTheme, children ∷ Array JSX }
|
||||
( ReactComponent { defaultTheme ∷ DefaultTheme, themes ∷ Array DefaultTheme, kids ∷ Array JSX }
|
||||
)
|
||||
mkThemeSwitcher = do
|
||||
themeProvider <- mkThemeProvider
|
||||
@ -67,27 +70,28 @@ mkThemeSwitcher = do
|
||||
makeStyles_
|
||||
{ selector:
|
||||
cssSafer
|
||||
{ position: "absolute"
|
||||
{ position: "fixed"
|
||||
, zIndex: 20
|
||||
, top: 10
|
||||
, right: 10
|
||||
}
|
||||
, "@font-face": Font.arrayToCss (Rubik.fontFamilies <> [ PragmataPro.fontFamily ])
|
||||
}
|
||||
storage <- window >>= localStorage
|
||||
saved ∷ (Maybe DefaultTheme) <- getItem "theme" storage <#> (_ >>= readJSON_)
|
||||
component "ThemeSwitcher" \{ defaultTheme, themes, children } -> React.do
|
||||
component "ThemeSwitcher" \{ defaultTheme, themes, kids } -> React.do
|
||||
classes <- useStyles
|
||||
{ theme, name } /\ modTheme <- useState $ fromMaybe defaultTheme saved
|
||||
let
|
||||
setTheme newTheme = do
|
||||
setItem "theme" (writeJSON newTheme) storage
|
||||
modTheme (const newTheme)
|
||||
|
||||
let
|
||||
handleClicked maybeValue =
|
||||
traverse_ setTheme do
|
||||
value <- maybeValue
|
||||
themes # find \x -> x.name == value
|
||||
|
||||
let
|
||||
themeSelect =
|
||||
R.select
|
||||
{ onChange: handler targetValue handleClicked
|
||||
@ -107,9 +111,9 @@ mkThemeSwitcher = do
|
||||
{ theme
|
||||
, children:
|
||||
[ R.div
|
||||
{ style: css { backgroundColor: theme.backgroundColour, width: "100%" }
|
||||
{ style: css { backgroundColor: theme.backgroundColour, width: "100%", height: "100%" }
|
||||
, children:
|
||||
[ themeSelect ] <> children
|
||||
[ themeSelect ] <> kids
|
||||
}
|
||||
]
|
||||
}
|
@ -3,11 +3,9 @@ module Storybook.React
|
||||
, Storybook
|
||||
, add
|
||||
, addDecorator
|
||||
)
|
||||
where
|
||||
) where
|
||||
|
||||
import Prelude hiding (add)
|
||||
|
||||
import Control.Monad.Reader (ReaderT, ask, lift, local, runReaderT)
|
||||
import Effect (Effect)
|
||||
import React.Basic (JSX, ReactComponent, element, fragment)
|
@ -1,16 +1,17 @@
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const path = require('path');
|
||||
const path = require("path");
|
||||
|
||||
const isWebpackDevServer = process.argv.some(a => path.basename(a) === 'webpack-dev-server');
|
||||
const isWebpackDevServer = process.argv.some(
|
||||
a => path.basename(a) === "webpack-dev-server"
|
||||
);
|
||||
|
||||
const isWatch = process.argv.some(a => a === '--watch');
|
||||
const isWatch = process.argv.some(a => a === "--watch");
|
||||
|
||||
module.exports = {
|
||||
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: 'bundle.js'
|
||||
path: path.resolve(__dirname, "dist"),
|
||||
filename: "bundle.js"
|
||||
},
|
||||
|
||||
module: {
|
||||
@ -19,13 +20,9 @@ module.exports = {
|
||||
test: /\.purs$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'purs-loader',
|
||||
loader: "purs-loader",
|
||||
options: {
|
||||
src: [
|
||||
'src/**/*.purs',
|
||||
'test/**/*.purs',
|
||||
'stories/**/*.purs',
|
||||
],
|
||||
src: ["src/**/*.purs", "test/**/*.purs", "stories/**/*.purs"],
|
||||
spago: true,
|
||||
watch: isWebpackDevServer || isWatch,
|
||||
pscIde: true
|
||||
@ -35,29 +32,32 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
test: /\.css$/i,
|
||||
use: ['style-loader', 'css-loader'],
|
||||
use: ["style-loader", "css-loader"]
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpg|gif)$/i,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
loader: "url-loader",
|
||||
options: {
|
||||
limit: 8192,
|
||||
},
|
||||
},
|
||||
],
|
||||
limit: 8192
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.svg$/,
|
||||
loader: 'react-svg-loader'
|
||||
loader: "react-svg-loader"
|
||||
},
|
||||
{
|
||||
test: /\.(woff|woff2|eot|ttf|otf)$/,
|
||||
use: ["file-loader"]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
resolve: {
|
||||
modules: [ 'node_modules' ],
|
||||
extensions: [ '.purs', '.js']
|
||||
modules: ["node_modules"],
|
||||
extensions: [".purs", ".js"]
|
||||
}
|
||||
|
||||
};
|
||||
|
16
components/.storybook/preview-head.html
Normal file
@ -0,0 +1,16 @@
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.2/animate.css"
|
||||
integrity="sha256-a2tobsqlbgLsWs7ZVUGgP5IvWZsx8bTNQpzsqCSm5mk="
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
<style>
|
||||
html,
|
||||
body,
|
||||
#app {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overscroll-behavior: none;
|
||||
background-color: black;
|
||||
}
|
||||
</style>
|
1
components/assets
Symbolic link
@ -0,0 +1 @@
|
||||
../assets/
|
@ -1 +0,0 @@
|
||||
<?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>
|
Before Width: | Height: | Size: 1.2 KiB |
@ -1 +0,0 @@
|
||||
<?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>
|
Before Width: | Height: | Size: 1.5 KiB |
@ -1 +0,0 @@
|
||||
<?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>
|
Before Width: | Height: | Size: 1.0 KiB |
@ -1 +0,0 @@
|
||||
<?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>
|
Before Width: | Height: | Size: 1.1 KiB |
@ -1 +0,0 @@
|
||||
<?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>
|
Before Width: | Height: | Size: 1.5 KiB |
@ -1 +0,0 @@
|
||||
<?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>
|
Before Width: | Height: | Size: 1.1 KiB |
@ -1 +0,0 @@
|
||||
<?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>
|
Before Width: | Height: | Size: 1.2 KiB |
@ -1 +0,0 @@
|
||||
<?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>
|
Before Width: | Height: | Size: 1.4 KiB |
@ -1 +0,0 @@
|
||||
<?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>
|
Before Width: | Height: | Size: 775 B |
@ -1 +0,0 @@
|
||||
<?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>
|
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 31 KiB |
@ -1 +0,0 @@
|
||||
<?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 101 72" 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.651" height="71.235" style="fill:none;"/><g id="Icon"><path d="M96.414,22.222l-18.005,-18.014l-4.857,4.857l15.576,15.585l-15.576,15.582l4.857,4.856l18.005,-18.007c0.649,-0.652 1.007,-1.516 1.007,-2.434c-0.003,-0.918 -0.358,-1.778 -1.007,-2.425" style="fill:#ccffd6;fill-rule:nonzero;"/><path d="M50.441,13.651c7.364,-7.356 19.315,-7.354 26.677,0.007c7.361,7.362 7.363,19.313 0.007,26.677l0.007,0.007l-26.684,26.684l-26.684,-26.684c-7.364,-7.363 -7.364,-19.32 0,-26.684c7.361,-7.361 19.312,-7.363 26.677,-0.007Z" style="fill:#c47dff;"/><path d="M27.102,26.276l-4.859,-4.858l-18.012,18.01c-0.647,0.647 -1.004,1.511 -1.002,2.428c0,0.919 0.355,1.781 1.002,2.428l18.012,18.012l4.859,-4.856l-15.583,-15.584l15.583,-15.58Z" style="fill:#ccffd6;fill-rule:nonzero;"/></g></svg>
|
Before Width: | Height: | Size: 1.2 KiB |
@ -1 +0,0 @@
|
||||
<?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>
|
Before Width: | Height: | Size: 2.0 KiB |
@ -1 +0,0 @@
|
||||
<?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>
|
Before Width: | Height: | Size: 1.9 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 100 100" fill-rule="nonzero" stroke-linejoin="round" stroke-miterlimit="2"><path d="M28.72 46.524l8.94.26-7.843 7.388h40.97l-7.87 6.732H29.753l7.64 7.302-8.76.267-10.928-10.88 11.013-11.07zM17.493 57.806l.213-.213-.213.213z" fill="#fafafa"/><path d="M71.3 53.472l-8.94-.26 7.843-7.388H29.4l7.723-6.732h33.163l-7.64-7.302 8.758-.267 10.93 10.88L71.3 53.472zM82.536 42.2l-.213.213.213-.213z" fill="#fff" fill-opacity=".14"/></svg>
|
Before Width: | Height: | Size: 508 B |
@ -1,3 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
|
||||
<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>
|
Before Width: | Height: | Size: 907 B |
@ -1 +0,0 @@
|
||||
<?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 39 34" 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;"><path d="M0,33.021l12.425,-21.521l3.753,6.5l-8.672,15.021l-7.506,0Zm24.85,0l-11.571,0l5.785,-10.021l5.786,10.021Zm13.279,0l-7.506,0l-15.311,-26.521l3.752,-6.5l19.065,33.021Z"/></svg>
|
Before Width: | Height: | Size: 622 B |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 30 KiB |
935
components/package-lock.json
generated
@ -11,7 +11,9 @@
|
||||
},
|
||||
"scripts": {
|
||||
"test": "spago test",
|
||||
"build": "spago build && webpack --config webpack.production.js",
|
||||
"build": "run-s build:*",
|
||||
"build:tsc": "tsc -p src/",
|
||||
"build:ps": "spago build && webpack --config webpack.production.js",
|
||||
"start:local": "webpack",
|
||||
"webpack": "DEBUG=purs-loader* DEBUG_DEPTH=100 webpack --config webpack.dev.js --progress --bail",
|
||||
"webpack:watch": "DEBUG=purs-loader* DEBUG_DEPTH=100 webpack --config webpack.dev.js --progress --display-error-details --display verbose --watch",
|
||||
@ -32,14 +34,8 @@
|
||||
"homepage": "https://github.com/i-am-the-slime/psfp#readme",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@material-ui/styles": "^4.4.3",
|
||||
"@monaco-editor/react": "^1.2.2",
|
||||
"purty": "^4.5.1",
|
||||
"react": "^16.9.0",
|
||||
"react-dom": "^16.9.0",
|
||||
"react-hot-loader": "^4.12.15",
|
||||
"smoothscroll-polyfill": "^0.4.4",
|
||||
"@babel/core": "^7.6.0",
|
||||
"@material-ui/styles": "^4.4.3",
|
||||
"@storybook/react": "^5.2.0",
|
||||
"@testing-library/react": "^9.1.4",
|
||||
"babel-loader": "^8.0.6",
|
||||
@ -47,11 +43,21 @@
|
||||
"deep-equal": "^1.1.0",
|
||||
"jsdom": "^15.1.1",
|
||||
"jsdom-global": "^3.0.2",
|
||||
"monaco-editor": "^0.20.0",
|
||||
"monaco-editor-webpack-plugin": "^1.8.2",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"purescript": "^0.13.6",
|
||||
"purescript-psa": "^0.7.3",
|
||||
"purs-loader": "^3.6.0",
|
||||
"purty": "^4.5.1",
|
||||
"react": "^16.9.0",
|
||||
"react-dom": "^16.9.0",
|
||||
"react-hot-loader": "^4.12.15",
|
||||
"react-monaco-editor": "^0.33.0",
|
||||
"react-svg-loader": "^3.0.3",
|
||||
"smoothscroll-polyfill": "^0.4.4",
|
||||
"spago": "^0.13.1",
|
||||
"typescript": "^3.7.5",
|
||||
"webpack": "^4.41.0",
|
||||
"webpack-cli": "^3.3.6",
|
||||
"webpack-dev-server": "^3.8.1",
|
||||
|
@ -2,13 +2,13 @@
|
||||
Welcome to a Spago project!
|
||||
You can edit this file as you like.
|
||||
-}
|
||||
{ name =
|
||||
"my-project"
|
||||
{ name = "my-project"
|
||||
, dependencies =
|
||||
[ "console"
|
||||
, "css"
|
||||
, "debug"
|
||||
, "effect"
|
||||
, "interpolate"
|
||||
, "matryoshka"
|
||||
, "milkis"
|
||||
, "psci-support"
|
||||
@ -21,8 +21,6 @@ You can edit this file as you like.
|
||||
, "string-parsers"
|
||||
, "web-html"
|
||||
]
|
||||
, packages =
|
||||
./packages.dhall
|
||||
, sources =
|
||||
[ "src/**/*.purs", "test/**/*.purs" ]
|
||||
, packages = ./packages.dhall
|
||||
, sources = [ "src/**/*.purs", "test/**/*.purs" ]
|
||||
}
|
||||
|
@ -1,16 +1,18 @@
|
||||
module Button.Component where
|
||||
|
||||
import Prelude
|
||||
import CSS (ColorSpace(..), mix, toHexString)
|
||||
import CSS (ColorSpace(..), contentBox, mix, toHexString)
|
||||
import CSS.Safer (cssSafer)
|
||||
import Color (fromHexString)
|
||||
import Data.Foldable (intercalate)
|
||||
import Data.Interpolate (i)
|
||||
import Data.Maybe (fromMaybe)
|
||||
import Data.Monoid (guard)
|
||||
import Effect (Effect)
|
||||
import Prim.Row (class Lacks, class Union)
|
||||
import React.Basic (JSX)
|
||||
import React.Basic.DOM (Props_button, unsafeCreateDOMComponent)
|
||||
import React.Basic.DOM as R
|
||||
import React.Basic.Hooks (ReactComponent, component, element)
|
||||
import React.Basic.Hooks as React
|
||||
import Record (union)
|
||||
@ -42,7 +44,17 @@ mkButton ∷
|
||||
mkButton = do
|
||||
useStyles <-
|
||||
makeStyles \(theme ∷ CSSTheme) ->
|
||||
{ "@keyframes gradientBG":
|
||||
{ buttonContainer:
|
||||
cssSafer
|
||||
{ padding: "2px"
|
||||
, background: linearGradient [ "145deg", theme.highlightColour, theme.highlightColourDark ]
|
||||
, borderRadius: "20px"
|
||||
, height: "40px"
|
||||
, minWidth: "100px"
|
||||
, boxSizing: "border-box"
|
||||
, margin: "2px"
|
||||
}
|
||||
, "@keyframes gradientBG":
|
||||
cssSafer
|
||||
{ "0%": { backgroundPosition: "0% 50%" }
|
||||
, "50%": { backgroundPosition: "100% 50%" }
|
||||
@ -51,38 +63,25 @@ mkButton = do
|
||||
, btn:
|
||||
cssSafer
|
||||
{ background:
|
||||
if theme.isLight then
|
||||
theme.interfaceColourLightest
|
||||
else
|
||||
linearGradient
|
||||
[ theme.interfaceColourLightest
|
||||
, theme.interfaceColourLighter
|
||||
]
|
||||
, color: theme.textColour
|
||||
, boxShadow:
|
||||
if theme.isLight then
|
||||
"none"
|
||||
else
|
||||
"1px 1px 10px rgba(0,0,0,0.66)"
|
||||
, border:
|
||||
if theme.isLight then
|
||||
"1px solid " <> theme.interfaceColourLighter
|
||||
else
|
||||
"none"
|
||||
linearGradient
|
||||
[ "145deg"
|
||||
, theme.interfaceColourLightest
|
||||
, theme.interfaceColourDarkest
|
||||
]
|
||||
, color: theme.highlightColour --theme.textColour
|
||||
, borderRadius: "20px"
|
||||
, padding: "0px 18px 0px 18px"
|
||||
, marginLeft: "2px"
|
||||
, marginRight: "2px"
|
||||
, minWidth: "100px"
|
||||
, height: "40px"
|
||||
, border: "0"
|
||||
, width: "100%"
|
||||
, height: "36px"
|
||||
, fontFamily: theme.textFontFamily
|
||||
, padding: "1px 18px 0px 18px"
|
||||
, letterSpacing: "0.2em"
|
||||
, textTransform: "uppercase"
|
||||
, outline: "none"
|
||||
, "&:focus":
|
||||
{ background:
|
||||
linearGradient
|
||||
[ "-5deg"
|
||||
[ "145deg"
|
||||
, theme.interfaceColourDarker
|
||||
, theme.highlightColourDark
|
||||
, theme.highlightColour
|
||||
@ -99,13 +98,19 @@ mkButton = do
|
||||
, animation: "$gradientBG 3s ease infinite"
|
||||
}
|
||||
, "&:active":
|
||||
{ background:
|
||||
{ boxShadow:
|
||||
( i "inset 6px 6px 6px "
|
||||
theme.backgroundColourDarkest
|
||||
", inset -6px -6px 6px "
|
||||
theme.backgroundColourLightest ::
|
||||
String
|
||||
)
|
||||
, background:
|
||||
linearGradient
|
||||
[ "180deg"
|
||||
, theme.interfaceColourLighter
|
||||
, theme.interfaceColourLightest
|
||||
[ "145deg"
|
||||
, theme.backgroundColourDarker
|
||||
, theme.backgroundColourLighter
|
||||
]
|
||||
, boxShadow: "inset 0 0 2px black"
|
||||
}
|
||||
, "&:disabled":
|
||||
{ boxShadow: "0 0 0 black"
|
||||
@ -124,7 +129,7 @@ mkButton = do
|
||||
linearGradient [ theme.highlightColour, theme.highlightColourDark ]
|
||||
, "&:active":
|
||||
{ background:
|
||||
linearGradient [ theme.highlightColourDark, theme.highlightColour ]
|
||||
linearGradient [ "145deg", theme.highlightColourDark, theme.highlightColour ]
|
||||
}
|
||||
, color:
|
||||
fromMaybe theme.textColour do
|
||||
@ -141,20 +146,26 @@ mkButton = do
|
||||
let
|
||||
classes = flip classNames rawClasses
|
||||
-- [TODO]: How do you do this in a typesafe manner?
|
||||
pure <<< (element $ unsafeCreateDOMComponent "button")
|
||||
$ { className:
|
||||
( classes
|
||||
[ _.btn
|
||||
, guard (buttonType == HighlightedButton) _.highlightedButton
|
||||
]
|
||||
)
|
||||
<> " "
|
||||
<> className
|
||||
, disabled: buttonType == DisabledButton
|
||||
, children: kids
|
||||
}
|
||||
`union`
|
||||
buttonProps
|
||||
pure
|
||||
$ R.div
|
||||
{ className: rawClasses.buttonContainer
|
||||
, children:
|
||||
[ (element $ unsafeCreateDOMComponent "button")
|
||||
$ { className:
|
||||
( classes
|
||||
[ _.btn
|
||||
, guard (buttonType == HighlightedButton) _.highlightedButton
|
||||
]
|
||||
)
|
||||
<> " "
|
||||
<> className
|
||||
, disabled: buttonType == DisabledButton
|
||||
, children: kids
|
||||
}
|
||||
`union`
|
||||
buttonProps
|
||||
]
|
||||
}
|
||||
|
||||
linearGradient ∷ Array String -> String
|
||||
linearGradient elems = "linear-gradient(" <> intercalate "," elems <> ")"
|
||||
|
@ -2,6 +2,7 @@ module Card.Component where
|
||||
|
||||
import Prelude
|
||||
import CSS.Safer (cssSafer)
|
||||
import Data.Interpolate (i)
|
||||
import Effect (Effect)
|
||||
import React.Basic (JSX)
|
||||
import React.Basic.DOM as R
|
||||
@ -22,14 +23,13 @@ mkCard = do
|
||||
makeStyles \(theme ∷ CSSTheme) ->
|
||||
{ card:
|
||||
cssSafer
|
||||
{ background: theme.interfaceColourLighter
|
||||
{ background: (i "linear-gradient(145deg," theme.backgroundColourDarker ", " theme.backgroundColourLighter ")") :: String
|
||||
, color: theme.textColour
|
||||
, fontFamily: theme.textFontFamily
|
||||
, margin: "20px"
|
||||
, boxShadow:
|
||||
"1px 1px 20px rgba(0,0,0,0."
|
||||
<> (if theme.isLight then "17" else "43")
|
||||
<> ")"
|
||||
, borderRadius: "5px"
|
||||
(i "30px 30px 60px " theme.backgroundColourDarker ", -30px -30px 60px " theme.backgroundColourLighter ";") :: String
|
||||
, borderRadius: "15px"
|
||||
, padding: "36px 40px 32px 40px"
|
||||
}
|
||||
}
|
||||
|
@ -7,14 +7,16 @@ import Card.Component (mkCard)
|
||||
import Data.Array (intercalate)
|
||||
import Data.Either (Either(..))
|
||||
import Data.Foldable (for_)
|
||||
import Data.Interpolate (i)
|
||||
import Data.Maybe (Maybe(..))
|
||||
import Data.Tuple.Nested ((/\))
|
||||
import Debug.Trace (spy)
|
||||
import Editor (getValue, mkEditor, setValue)
|
||||
import Effect (Effect)
|
||||
import Effect.Aff (Aff, error, launchAff_, throwError)
|
||||
import Effect.Aff (Aff, attempt, error, launchAff_, message, throwError)
|
||||
import Effect.Class (liftEffect)
|
||||
import Milkis as M
|
||||
import Milkis.Impl.Window (windowFetch)
|
||||
import Milkis.Impl (FetchImpl)
|
||||
import React.Basic (ReactComponent)
|
||||
import React.Basic.DOM as R
|
||||
import React.Basic.Events (handler_)
|
||||
@ -29,8 +31,8 @@ import Theme.Types (CSSTheme)
|
||||
type Props
|
||||
= { initialCode :: String, height :: String }
|
||||
|
||||
mkCompileEditor ∷ Effect (ReactComponent Props)
|
||||
mkCompileEditor = do
|
||||
mkCompileEditor ∷ FetchImpl -> Effect (ReactComponent Props)
|
||||
mkCompileEditor fetch = do
|
||||
editor <- mkEditor
|
||||
card <- mkCard
|
||||
button <- mkButton
|
||||
@ -38,28 +40,39 @@ mkCompileEditor = do
|
||||
makeStyles \(theme :: CSSTheme) ->
|
||||
{ editor:
|
||||
cssSafer
|
||||
{ background: theme.codeBackgroundColour
|
||||
{ background: theme.backgroundColour
|
||||
, height: "80%"
|
||||
, padding: "20px"
|
||||
, margin: "20px"
|
||||
, marginTop: "0px"
|
||||
, marginLeft: "35px"
|
||||
, marginRight: "35px"
|
||||
, marginBottom: "35px"
|
||||
, borderRadius: "12px"
|
||||
, boxShadow: i "22px 22px 24px " theme.backgroundColourDarker ", -22px -22px 24px " theme.backgroundColourLighter :: String
|
||||
, display: "flex"
|
||||
, flexDirection: "column"
|
||||
}
|
||||
, buttons:
|
||||
cssSafer
|
||||
{ marginBottom: "4px"
|
||||
, display: "flex"
|
||||
, alignSelf: "flex-end"
|
||||
}
|
||||
, buttons: cssSafer { float: "right", marginRight: "40px", height: "30px" }
|
||||
, compileButton: cssSafer {}
|
||||
, resetButton: cssSafer {}
|
||||
, card:
|
||||
cssSafer
|
||||
{ marginTop: "70px"
|
||||
{ marginTop: "120px"
|
||||
, marginLeft: "35px"
|
||||
, marginRight: "35px"
|
||||
, opacity: 0
|
||||
, zIndex: 0
|
||||
}
|
||||
, cardHidden: cssSafer { opacity: 0 }
|
||||
, compileError: cssSafer { color: theme.red, animation: "0.7s shake ease" }
|
||||
, runOutput: cssSafer { color: theme.green, animation: "0.4s bounceIn ease" }
|
||||
, compileError: cssSafer { color: theme.red, opacity: 1, transition: "opacity 2.0s ease" }
|
||||
, runOutput: cssSafer { color: theme.green, opacity: 1, transition: "opacity 2.0s ease" }
|
||||
}
|
||||
component "StorybookEditor" \{ initialCode, height } -> React.do
|
||||
component "CompileEditor" \{ initialCode, height } -> React.do
|
||||
maybeEditor /\ modifyEditor <- useState Nothing
|
||||
classes <- useStyles
|
||||
let
|
||||
@ -89,34 +102,36 @@ mkCompileEditor = do
|
||||
setCompileResult Nothing
|
||||
code <- getValue ed
|
||||
launchAff_ do
|
||||
res <- compileAndRun { code }
|
||||
res <- compileAndRun (M.fetch fetch) { code }
|
||||
setCompileResult (Just res) # liftEffect
|
||||
pure
|
||||
$ fragment
|
||||
[ R.div
|
||||
{ children: [ element editor { onLoad, height } ]
|
||||
, className: classes.editor
|
||||
}
|
||||
, R.div
|
||||
{ className: classes.buttons
|
||||
, children:
|
||||
[ element button
|
||||
{ buttonType: PlainButton
|
||||
, kids: [ R.text "Reset" ]
|
||||
, buttonProps:
|
||||
{ onClick: handler_ reset
|
||||
}
|
||||
, className: classes.resetButton
|
||||
}
|
||||
, element button
|
||||
{ buttonType: HighlightedButton
|
||||
, kids: [ R.text "Compile" ]
|
||||
, buttonProps:
|
||||
{ onClick: handler_ compile
|
||||
}
|
||||
, className: classes.compileButton
|
||||
{ children:
|
||||
[ R.div
|
||||
{ className: classes.buttons
|
||||
, children:
|
||||
[ element button
|
||||
{ buttonType: PlainButton
|
||||
, kids: [ R.text "Reset" ]
|
||||
, buttonProps:
|
||||
{ onClick: handler_ reset
|
||||
}
|
||||
, className: classes.resetButton
|
||||
}
|
||||
, element button
|
||||
{ buttonType: HighlightedButton
|
||||
, kids: [ R.text "Compile" ]
|
||||
, buttonProps:
|
||||
{ onClick: handler_ compile
|
||||
}
|
||||
, className: classes.compileButton
|
||||
}
|
||||
]
|
||||
}
|
||||
, element editor { onLoad, height }
|
||||
]
|
||||
, className: classes.editor
|
||||
}
|
||||
, element card
|
||||
{ kids: [ R.text (compileResultToString compileResult) ]
|
||||
@ -124,18 +139,39 @@ mkCompileEditor = do
|
||||
}
|
||||
]
|
||||
|
||||
fetch ∷ M.Fetch
|
||||
fetch = M.fetch windowFetch
|
||||
|
||||
compileAndRun :: Body.CompileRequest -> Aff (Either Body.CompileResult Body.RunResult)
|
||||
compileAndRun body = do
|
||||
compileAndRun :: M.Fetch -> Body.CompileRequest -> Aff (Either Body.CompileResult Body.RunResult)
|
||||
compileAndRun fetch body = do
|
||||
response <-
|
||||
fetch (M.URL "/api/compileAndRun")
|
||||
{ method: M.postMethod
|
||||
, body: writeJSON body
|
||||
, headers: M.makeHeaders { "Content-Type": "application/json" }
|
||||
}
|
||||
case M.statusCode response of
|
||||
200 -> M.json response >>= readAff <#> Right
|
||||
422 -> M.json response >>= readAff <#> Left
|
||||
code -> throwError (error $ "Unexpected response code " <> show code)
|
||||
attempt
|
||||
$ fetch (M.URL "/api/compileAndRun")
|
||||
{ method: M.postMethod
|
||||
, body: writeJSON body
|
||||
, headers: M.makeHeaders { "Content-Type": "application/json" }
|
||||
}
|
||||
case spy "resp" response of
|
||||
Left l ->
|
||||
pure
|
||||
( Left
|
||||
{ resultType: ""
|
||||
, result:
|
||||
[ { allSpans: []
|
||||
, errorCode: ""
|
||||
, errorLink: ""
|
||||
, filename: ""
|
||||
, message: message l
|
||||
, moduleName: Nothing
|
||||
, position:
|
||||
{ endColumn: 0
|
||||
, endLine: 0
|
||||
, startColumn: 0
|
||||
, startLine: 0
|
||||
}
|
||||
, suggestion: Nothing
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
Right r -> case M.statusCode r of
|
||||
200 -> M.json r >>= readAff <#> Right
|
||||
422 -> M.json r >>= readAff <#> Left
|
||||
code -> throwError (error $ "Unexpected response code " <> show code)
|
||||
|
16
components/src/Yoga/Font.purs
Normal file
@ -0,0 +1,16 @@
|
||||
module Yoga.Font where
|
||||
|
||||
import React.Basic.DOM (CSS)
|
||||
import Unsafe.Coerce (unsafeCoerce)
|
||||
|
||||
foreign import data Font :: Type
|
||||
|
||||
type FontFamily
|
||||
= { fontFamily :: String
|
||||
, fontStyle :: String
|
||||
, fontWeight :: String
|
||||
, src :: String
|
||||
}
|
||||
|
||||
arrayToCss :: Array FontFamily -> CSS
|
||||
arrayToCss = unsafeCoerce
|
1
components/src/Yoga/Font/PragmataPro.js
Normal file
@ -0,0 +1 @@
|
||||
exports.ppWoff2 = require("../../../assets/fonts/PragmataProLiga-Regular.woff2");
|
15
components/src/Yoga/Font/PragmataPro.purs
Normal file
@ -0,0 +1,15 @@
|
||||
module Yoga.Font.PragmataPro (fontFamily) where
|
||||
|
||||
import Prelude
|
||||
import Unsafe.Coerce (unsafeCoerce)
|
||||
import Yoga.Font (Font, FontFamily)
|
||||
|
||||
foreign import ppWoff2 :: Font
|
||||
|
||||
fontFamily :: FontFamily
|
||||
fontFamily =
|
||||
{ fontFamily: "PragmataPro"
|
||||
, src: "url(" <> unsafeCoerce ppWoff2 <> """) format("woff2")"""
|
||||
, fontStyle: "normal"
|
||||
, fontWeight: "normal"
|
||||
}
|
6
components/src/Yoga/Font/Rubik.js
Normal file
@ -0,0 +1,6 @@
|
||||
exports.rubikRegularwoff2 = require("../../../assets/fonts/Rubik-Regular.woff2");
|
||||
exports.rubikBoldwoff2 = require("../../../assets/fonts/Rubik-Bold.woff2");
|
||||
exports.rubikBoldItalicwoff2 = require("../../../assets/fonts/Rubik-BoldItalic.woff2");
|
||||
exports.rubikItalicwoff2 = require("../../../assets/fonts/Rubik-Italic.woff2");
|
||||
exports.rubikLightwoff2 = require("../../../assets/fonts/Rubik-Light.woff2");
|
||||
exports.rubikLightItalicwoff2 = require("../../../assets/fonts/Rubik-LightItalic.woff2");
|
51
components/src/Yoga/Font/Rubik.purs
Normal file
@ -0,0 +1,51 @@
|
||||
module Yoga.Font.Rubik (fontFamilies) where
|
||||
|
||||
import Prelude
|
||||
import Unsafe.Coerce (unsafeCoerce)
|
||||
import Yoga.Font (Font, FontFamily)
|
||||
|
||||
foreign import rubikRegularwoff2 :: Font
|
||||
|
||||
foreign import rubikBoldwoff2 :: Font
|
||||
|
||||
foreign import rubikBoldItalicwoff2 :: Font
|
||||
|
||||
foreign import rubikItalicwoff2 :: Font
|
||||
|
||||
foreign import rubikLightwoff2 :: Font
|
||||
|
||||
foreign import rubikLightItalicwoff2 :: Font
|
||||
|
||||
fontFamilies :: Array FontFamily
|
||||
fontFamilies =
|
||||
[ { fontFamily: "Rubik"
|
||||
, src: "url(" <> unsafeCoerce rubikItalicwoff2 <> """) format("woff2")"""
|
||||
, fontWeight: "normal"
|
||||
, fontStyle: "italic"
|
||||
}
|
||||
, { fontFamily: "Rubik"
|
||||
, src: "url(" <> unsafeCoerce rubikBoldwoff2 <> """) format("woff2")"""
|
||||
, fontWeight: "bold"
|
||||
, fontStyle: "normal"
|
||||
}
|
||||
, { fontFamily: "Rubik"
|
||||
, src: "url(" <> unsafeCoerce rubikBoldItalicwoff2 <> """) format("woff2")"""
|
||||
, fontWeight: "bold"
|
||||
, fontStyle: "italic"
|
||||
}
|
||||
, { fontFamily: "Rubik"
|
||||
, src: "url(" <> unsafeCoerce rubikItalicwoff2 <> """) format("woff2")"""
|
||||
, fontWeight: "400"
|
||||
, fontStyle: "normal"
|
||||
}
|
||||
, { fontFamily: "Rubik Light"
|
||||
, src: "url(" <> unsafeCoerce rubikLightItalicwoff2 <> """) format("woff2")"""
|
||||
, fontWeight: "400"
|
||||
, fontStyle: "italic"
|
||||
}
|
||||
, { fontFamily: "Rubik"
|
||||
, src: "url(" <> unsafeCoerce rubikRegularwoff2 <> """) format("woff2")"""
|
||||
, fontWeight: "normal"
|
||||
, fontStyle: "normal"
|
||||
}
|
||||
]
|
@ -4,37 +4,43 @@ import Prelude
|
||||
import CSS.Safer (cssSafer)
|
||||
import Control.Promise (Promise)
|
||||
import Control.Promise as Promise
|
||||
import Data.Maybe (Maybe(..), maybe)
|
||||
import Data.Nullable (Nullable)
|
||||
import Data.Tuple.Nested ((/\))
|
||||
import Effect (Effect)
|
||||
import Effect.Aff (Aff)
|
||||
import Effect.Class (liftEffect)
|
||||
import Effect.Uncurried (EffectFn2, mkEffectFn2)
|
||||
import Effect.Unsafe (unsafePerformEffect)
|
||||
import Foreign (Foreign, unsafeToForeign)
|
||||
import Prim.Row (class Union)
|
||||
import React.Basic (JSX, ReactComponent, element, fragment)
|
||||
import React.Basic (JSX, ReactComponent, Ref, element, fragment)
|
||||
import React.Basic.DOM as R
|
||||
import React.Basic.Hooks (component)
|
||||
import React.Basic.Hooks (component, useState)
|
||||
import React.Basic.Hooks as React
|
||||
import React.Basic.Hooks.Aff (useAff)
|
||||
import Theme.Styles (makeStyles, useTheme)
|
||||
import Theme.Types (CSSTheme)
|
||||
import Web.DOM (Node)
|
||||
import Web.HTML (HTMLElement)
|
||||
|
||||
type EditorProps
|
||||
= ( value ∷ String
|
||||
, language ∷ String
|
||||
, editorDidMount ∷ EffectFn2 Node Editor Unit
|
||||
, editorDidMount ∷ EffectFn2 Editor Node Unit
|
||||
, editorWillMount ∷ Monaco -> Unit
|
||||
, theme ∷ String
|
||||
, line ∷ Number
|
||||
, ref ∷ Ref (Nullable HTMLElement)
|
||||
, width ∷ String
|
||||
, height ∷ String
|
||||
, loading ∷ JSX
|
||||
, options ∷ Foreign
|
||||
)
|
||||
|
||||
foreign import editorImpl ∷ ∀ attrs. ReactComponent { | attrs }
|
||||
|
||||
foreign import initMonacoImpl ∷ Effect (Promise Monaco)
|
||||
foreign import monacoEditorImpl ∷ ∀ attrs. Effect (Promise (ReactComponent { | attrs }))
|
||||
|
||||
-- foreign import initMonacoImpl ∷ Effect (Promise Monaco)
|
||||
foreign import defineThemeImpl ∷ Monaco -> String -> MonacoTheme -> Effect Unit
|
||||
|
||||
foreign import setThemeImpl ∷ Monaco -> String -> Effect Unit
|
||||
@ -53,12 +59,13 @@ foreign import data Editor ∷ Type
|
||||
|
||||
foreign import data MonacoTheme ∷ Type
|
||||
|
||||
editor ∷ ∀ attrs attrs_. Union attrs attrs_ EditorProps => ReactComponent { | attrs }
|
||||
editor = editorImpl
|
||||
|
||||
initMonaco ∷ Aff Monaco
|
||||
initMonaco = liftEffect initMonacoImpl >>= Promise.toAff
|
||||
monacoEditor ∷ ∀ attrs attrs_. Union attrs attrs_ EditorProps => Aff (ReactComponent { | attrs })
|
||||
monacoEditor = do
|
||||
prom <- monacoEditorImpl # liftEffect
|
||||
Promise.toAff prom
|
||||
|
||||
-- initMonaco ∷ Aff Monaco
|
||||
-- initMonaco = liftEffect initMonacoImpl >>= Promise.toAff
|
||||
darkThemeName ∷ String
|
||||
darkThemeName = "NightOwl"
|
||||
|
||||
@ -73,9 +80,8 @@ foreign import registerLanguageImpl ∷ Monaco -> String -> Effect Unit
|
||||
|
||||
foreign import setMonarchTokensProviderImpl ∷ Monaco -> String -> MonarchLanguage -> Effect Unit
|
||||
|
||||
initEditor ∷ Aff Unit
|
||||
initEditor = do
|
||||
monaco <- initMonaco
|
||||
initEditor ∷ Monaco -> Effect Unit
|
||||
initEditor monaco = do
|
||||
defineThemeImpl monaco darkThemeName nightOwlTheme # liftEffect
|
||||
defineThemeImpl monaco lightThemeName vsCodeTheme # liftEffect
|
||||
registerLanguageImpl monaco "purescript" # liftEffect
|
||||
@ -83,7 +89,7 @@ initEditor = do
|
||||
|
||||
type Props
|
||||
= { onLoad ∷ Editor -> Effect Unit
|
||||
, height :: String
|
||||
, height ∷ String
|
||||
}
|
||||
|
||||
mkEditor ∷ Effect (ReactComponent Props)
|
||||
@ -101,7 +107,10 @@ mkEditor = do
|
||||
}
|
||||
component "Editor" \{ onLoad, height } -> React.do
|
||||
classes <- useStyles
|
||||
useAff unit initEditor
|
||||
maybeEditor /\ modifyEditor <- useState Nothing
|
||||
useAff unit do
|
||||
eddy <- monacoEditor
|
||||
liftEffect $ modifyEditor (const (Just eddy))
|
||||
theme <- useTheme
|
||||
let
|
||||
themeName = if theme.isLight then lightThemeName else darkThemeName
|
||||
@ -110,27 +119,30 @@ mkEditor = do
|
||||
[ R.div
|
||||
{ className: classes.wrapper
|
||||
, children:
|
||||
[ element editor
|
||||
{ theme: themeName
|
||||
, height
|
||||
, options:
|
||||
unsafeToForeign
|
||||
{ fontFamily: "PragmataPro"
|
||||
, fontLigatures: true
|
||||
, fontSize: "16pt"
|
||||
, lineNumbers: "off"
|
||||
, glyphMargin: false
|
||||
, folding: false
|
||||
, lineDecorationsWidth: 0
|
||||
, lineNumbersMinChars: 0
|
||||
, minimap: { enabled: false }
|
||||
, scrollBeyondLastLine: false
|
||||
}
|
||||
, language: "purescript"
|
||||
-- https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-custom-languages
|
||||
, editorDidMount:
|
||||
mkEffectFn2 \_ -> onLoad
|
||||
}
|
||||
[ maybeEditor
|
||||
# maybe mempty \editor ->
|
||||
element editor
|
||||
{ theme: themeName
|
||||
, height
|
||||
, options:
|
||||
unsafeToForeign
|
||||
{ fontFamily: "PragmataPro"
|
||||
, fontLigatures: true
|
||||
, fontSize: "16pt"
|
||||
, lineNumbers: "off"
|
||||
, glyphMargin: false
|
||||
, folding: false
|
||||
, lineDecorationsWidth: 0
|
||||
, lineNumbersMinChars: 0
|
||||
, minimap: { enabled: false }
|
||||
, scrollBeyondLastLine: false
|
||||
}
|
||||
, language: "purescript"
|
||||
-- https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-custom-languages
|
||||
, editorDidMount:
|
||||
mkEffectFn2 \e _ -> onLoad e
|
||||
, editorWillMount: \x -> unsafePerformEffect (initEditor x)
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
1019
components/src/Yoga/Monaco/Editor.ts
Normal file
@ -13,6 +13,7 @@ var map = require("../../../assets/icons/map.svg");
|
||||
var mapflipped = require("../../../assets/icons/mapflipped.svg");
|
||||
var pslogo = require("../../../assets/icons/pslogo.svg");
|
||||
var trianglelogo = require("../../../assets/icons/trianglelogo.svg");
|
||||
var play = require("../../../assets/icons/play.svg");
|
||||
|
||||
exports.alternativeIconRaw = alternative.default;
|
||||
exports.apIconRaw = ap.default;
|
||||
@ -27,3 +28,4 @@ exports.mapIconRaw = map.default;
|
||||
exports.mapflippedIconRaw = mapflipped.default;
|
||||
exports.pslogoIconRaw = pslogo.default;
|
||||
exports.trianglelogoIconRaw = trianglelogo.default;
|
||||
exports.playIconRaw = play.default;
|
||||
|
@ -1,7 +1,6 @@
|
||||
module SVG.Icon where
|
||||
|
||||
import Prelude
|
||||
|
||||
import CSS.Safer (cssSafer)
|
||||
import Data.Monoid (guard)
|
||||
import Effect (Effect)
|
||||
@ -13,62 +12,81 @@ import Theme.Styles (makeStyles)
|
||||
import Theme.Types (CSSTheme)
|
||||
import Unsafe.Coerce (unsafeCoerce)
|
||||
|
||||
type ImageProps = ( width ∷ Int, height ∷ Int, className ∷ String )
|
||||
type ImageProps
|
||||
= ( width ∷ Int, height ∷ Int, className ∷ String )
|
||||
|
||||
type Raw r = ReactComponent { | r }
|
||||
type Raw r
|
||||
= ReactComponent { | r }
|
||||
|
||||
foreign import alternativeIconRaw ∷ ∀ r. Raw r
|
||||
|
||||
alternativeIcon ∷ ∀ attrs attrs_. Union attrs attrs_ ImageProps => ReactComponent { | attrs }
|
||||
alternativeIcon = unsafeCoerce alternativeIconRaw
|
||||
|
||||
foreign import apIconRaw ∷ ∀ r. Raw r
|
||||
|
||||
apIcon ∷ ∀ attrs attrs_. Union attrs attrs_ ImageProps => ReactComponent { | attrs }
|
||||
apIcon = unsafeCoerce apIconRaw
|
||||
|
||||
foreign import appendIconRaw ∷ ∀ r. Raw r
|
||||
|
||||
appendIcon ∷ ∀ attrs attrs_. Union attrs attrs_ ImageProps => ReactComponent { | attrs }
|
||||
appendIcon = unsafeCoerce appendIconRaw
|
||||
|
||||
foreign import applyIconRaw ∷ ∀ r. Raw r
|
||||
|
||||
applyIcon ∷ ∀ attrs attrs_. Union attrs attrs_ ImageProps => ReactComponent { | attrs }
|
||||
applyIcon = unsafeCoerce applyIconRaw
|
||||
|
||||
foreign import applyflippedIconRaw ∷ ∀ r. Raw r
|
||||
|
||||
applyflippedIcon ∷ ∀ attrs attrs_. Union attrs attrs_ ImageProps => ReactComponent { | attrs }
|
||||
applyflippedIcon = unsafeCoerce applyflippedIconRaw
|
||||
|
||||
foreign import bindIconRaw ∷ ∀ r. Raw r
|
||||
|
||||
bindIcon ∷ ∀ attrs attrs_. Union attrs attrs_ ImageProps => ReactComponent { | attrs }
|
||||
bindIcon = unsafeCoerce bindIconRaw
|
||||
|
||||
foreign import composeIconRaw ∷ ∀ r. Raw r
|
||||
|
||||
composeIcon ∷ ∀ attrs attrs_. Union attrs attrs_ ImageProps => ReactComponent { | attrs }
|
||||
composeIcon = unsafeCoerce composeIconRaw
|
||||
|
||||
foreign import forallIconRaw ∷ ∀ r. Raw r
|
||||
|
||||
forallIcon ∷ ∀ attrs attrs_. Union attrs attrs_ ImageProps => ReactComponent { | attrs }
|
||||
forallIcon = unsafeCoerce forallIconRaw
|
||||
|
||||
foreign import kleisliIconRaw ∷ ∀ r. Raw r
|
||||
|
||||
kleisliIcon ∷ ∀ attrs attrs_. Union attrs attrs_ ImageProps => ReactComponent { | attrs }
|
||||
kleisliIcon = unsafeCoerce kleisliIconRaw
|
||||
|
||||
foreign import mapIconRaw ∷ ∀ r. Raw r
|
||||
|
||||
mapIcon ∷ ∀ attrs attrs_. Union attrs attrs_ ImageProps => ReactComponent { | attrs }
|
||||
mapIcon = unsafeCoerce mapIconRaw
|
||||
|
||||
foreign import mapflippedIconRaw ∷ ∀ r. Raw r
|
||||
|
||||
mapflippedIcon ∷ ∀ attrs attrs_. Union attrs attrs_ ImageProps => ReactComponent { | attrs }
|
||||
mapflippedIcon = unsafeCoerce mapflippedIconRaw
|
||||
|
||||
foreign import pslogoIconRaw ∷ ∀ r. Raw r
|
||||
|
||||
pslogoIcon ∷ ∀ attrs attrs_. Union attrs attrs_ ImageProps => ReactComponent { | attrs }
|
||||
pslogoIcon = unsafeCoerce pslogoIconRaw
|
||||
|
||||
foreign import trianglelogoIconRaw ∷ ∀ r. Raw r
|
||||
|
||||
trianglelogoIcon ∷ ∀ attrs attrs_. Union attrs attrs_ ImageProps => ReactComponent { | attrs }
|
||||
trianglelogoIcon = unsafeCoerce trianglelogoIconRaw
|
||||
|
||||
foreign import playIconRaw ∷ ∀ r. Raw r
|
||||
|
||||
playIcon ∷ ∀ attrs attrs_. Union attrs attrs_ ImageProps => ReactComponent { | attrs }
|
||||
playIcon = unsafeCoerce playIconRaw
|
||||
|
||||
data ActiveArrowDirection
|
||||
= ArrowPointsRight
|
||||
@ -80,19 +98,22 @@ mkMenu ∷ Effect (ReactComponent { activeArrowDirection ∷ ActiveArrowDirectio
|
||||
mkMenu = do
|
||||
useStyles <-
|
||||
makeStyles \(theme ∷ CSSTheme) ->
|
||||
{ arrow: cssSafer
|
||||
{ arrow:
|
||||
cssSafer
|
||||
{ fill: theme.textColour
|
||||
, transition: "0.3s ease-out"
|
||||
}
|
||||
, arrowInactive: cssSafer
|
||||
, arrowInactive:
|
||||
cssSafer
|
||||
{ fillOpacity: ".1"
|
||||
}
|
||||
, svg: cssSafer
|
||||
, svg:
|
||||
cssSafer
|
||||
{ width: "100%"
|
||||
, height: "100%"
|
||||
, "&:hover":
|
||||
{ fill: theme.backgroundColour
|
||||
}
|
||||
{ fill: theme.backgroundColour
|
||||
}
|
||||
}
|
||||
}
|
||||
component "MenuIcon" \{ activeArrowDirection } -> React.do
|
||||
|
@ -1,7 +1,7 @@
|
||||
module Theme where
|
||||
|
||||
import Prelude
|
||||
import CSS (ColorSpace(..), blue, brightness, contrast, darken, desaturate, isLight, lighten, mix, rotateHue, toHexString)
|
||||
import CSS (contrast, darken, isLight, lighten, rotateHue, toHexString)
|
||||
import Color (Color)
|
||||
import Data.Foldable (intercalate)
|
||||
import Data.Symbol (SProxy(..))
|
||||
@ -26,9 +26,14 @@ fromTheme ∷ Theme -> CSSTheme
|
||||
fromTheme theme =
|
||||
RB.build
|
||||
( {- background -} RB.modify (f ∷ _ "backgroundColour") toHexString
|
||||
>>> RB.modify (f ∷ _ "codeBackgroundColour") toHexString
|
||||
>>> RB.insert (f ∷ _ "backgroundColourLighter")
|
||||
(theme.backgroundColour # lighter >>> toHexString)
|
||||
>>> RB.insert (f ∷ _ "backgroundColourLightest")
|
||||
(theme.backgroundColour # lighter # lighter >>> toHexString)
|
||||
>>> RB.insert (f ∷ _ "backgroundColourDarker")
|
||||
(theme.backgroundColour # darker >>> toHexString)
|
||||
>>> RB.insert (f ∷ _ "backgroundColourDarkest")
|
||||
(theme.backgroundColour # darker # darker >>> toHexString)
|
||||
>>> RB.modify (f ∷ _ "interfaceColour") toHexString
|
||||
>>> RB.insert (f ∷ _ "interfaceColourLighter")
|
||||
(theme.interfaceColour # lighter >>> toHexString)
|
||||
@ -78,22 +83,8 @@ fromTheme theme =
|
||||
where
|
||||
isLightTheme = isLight theme.backgroundColour
|
||||
|
||||
yellower ∷ Color -> Color
|
||||
yellower col =
|
||||
if brightness col > 0.8 then
|
||||
lighten 0.02 col
|
||||
else
|
||||
col
|
||||
# lighten 0.1
|
||||
# desaturate 0.03
|
||||
|
||||
bluer col =
|
||||
mix HSL col blue 0.05
|
||||
# darken 0.1
|
||||
# desaturate 0.03
|
||||
|
||||
lighter ∷ Color -> Color
|
||||
lighter = yellower
|
||||
lighter = if isLightTheme then lighten 0.04 else lighten 0.02
|
||||
|
||||
darker ∷ Color -> Color
|
||||
darker = bluer
|
||||
darker = if isLightTheme then darken 0.01 else darken 0.01
|
||||
|
@ -2,21 +2,25 @@ module Theme.Default where
|
||||
|
||||
import Prelude
|
||||
import Color as Color
|
||||
import Data.Maybe (fromMaybe')
|
||||
import Partial.Unsafe (unsafeCrashWith)
|
||||
import Theme.Types (Theme)
|
||||
|
||||
systemFontStack ∷ Array String
|
||||
systemFontStack = [ "-apple-system", "BlinkMacSystemFont", "Helvetica", "Arial", "sans-serif" ]
|
||||
|
||||
hex :: String -> Color.Color
|
||||
hex c = c # Color.fromHexString # fromMaybe' \_ -> unsafeCrashWith $ "Invalid hex string " <> c
|
||||
|
||||
darkTheme ∷ Theme
|
||||
darkTheme =
|
||||
{ backgroundColour: Color.hsl 227.0 0.24 0.02
|
||||
, codeBackgroundColour: Color.rgb 0x1 0x16 0x27
|
||||
{ backgroundColour: Color.hsl 220.0 0.42 0.13
|
||||
, textColour: Color.hsl 225.0 0.28 0.90
|
||||
, interfaceColour: Color.hsl 225.0 0.48 0.12
|
||||
, highlightColour: Color.rgb 183 130 198
|
||||
, highlightColour: Color.rgb 209 51 225
|
||||
, altHighlightColour: Color.hsl 84.0 0.617 0.631
|
||||
, textFontFamily: [ "Rubik" ] <> systemFontStack
|
||||
, headingFontFamily: [ "Rubik" ] <> systemFontStack
|
||||
, textFontFamily: [ """Rubik""" ] <> systemFontStack
|
||||
, headingFontFamily: [ """Rubik""" ] <> systemFontStack
|
||||
, yellow: Color.rgb 255 235 149
|
||||
, green: Color.hsl 84.0 0.617 0.631
|
||||
, pink: Color.hsl 276.0 0.677 0.745
|
||||
@ -30,9 +34,8 @@ lightTheme ∷ Theme
|
||||
lightTheme =
|
||||
darkTheme
|
||||
{ textColour = Color.hsl 225.0 0.18 0.25
|
||||
, codeBackgroundColour = Color.hsl 227.0 0.24 0.02
|
||||
, backgroundColour = Color.hsl 210.0 0.00 0.98
|
||||
, interfaceColour = Color.hsl 210.0 0.10 0.70
|
||||
, backgroundColour = Color.hsl 230.0 0.35 0.90
|
||||
, interfaceColour = Color.hsl 210.0 0.30 0.80
|
||||
, highlightColour = Color.hsl 260.0 0.85 0.58
|
||||
, altHighlightColour = Color.hsl 84.0 0.617 0.631
|
||||
, green = Color.hsl 84.0 0.617 0.431
|
||||
|
@ -12,4 +12,4 @@ foreign import mkThemeProviderImpl ∷
|
||||
|
||||
mkThemeProvider ∷
|
||||
Effect (ReactComponent { children ∷ Array JSX, theme ∷ CSSTheme })
|
||||
mkThemeProvider = mkThemeProviderImpl
|
||||
mkThemeProvider = mkThemeProviderImpl
|
@ -4,7 +4,6 @@ import Color (Color)
|
||||
|
||||
type Theme
|
||||
= { backgroundColour ∷ Color
|
||||
, codeBackgroundColour ∷ Color
|
||||
, textColour ∷ Color
|
||||
, interfaceColour ∷ Color
|
||||
, highlightColour ∷ Color
|
||||
@ -22,8 +21,10 @@ type Theme
|
||||
|
||||
type CSSTheme
|
||||
= { backgroundColour ∷ String
|
||||
, codeBackgroundColour ∷ String
|
||||
, backgroundColourLighter ∷ String
|
||||
, backgroundColourLightest ∷ String
|
||||
, backgroundColourDarker ∷ String
|
||||
, backgroundColourDarkest ∷ String
|
||||
, interfaceColour ∷ String
|
||||
, interfaceColourDarker ∷ String
|
||||
, interfaceColourDarkest ∷ String
|
||||
|
@ -1,7 +1,6 @@
|
||||
module Typography.Header where
|
||||
|
||||
import Prelude
|
||||
|
||||
import CSS.Safer (cssSafer)
|
||||
import Data.Array as Array
|
||||
import Data.Foldable (intercalate)
|
||||
|
8
components/src/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "ES5",
|
||||
"sourceMap": false
|
||||
// "noImplicitAny": true
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
module ButtonStories where
|
||||
|
||||
import Prelude hiding (add)
|
||||
|
||||
import Button.Component (ButtonType(..), mkButton)
|
||||
import Decorator.FullScreen (fullScreenDecorator)
|
||||
import Effect (Effect)
|
||||
@ -16,7 +15,6 @@ stories ∷ Foreign -> Effect Storybook
|
||||
stories mod =
|
||||
storiesOf "Button" do
|
||||
addDecorator fullScreenDecorator
|
||||
|
||||
add "Button" mkExample
|
||||
[ { text: "Cancel"
|
||||
, buttonType: PlainButton
|
||||
@ -39,39 +37,41 @@ stories mod =
|
||||
, buttonProps: { onClick: handler_ (log "clicked very long...") }
|
||||
}
|
||||
]
|
||||
-- add "Icon Button" mkIconButton
|
||||
-- [ { icon: alternativeIcon, buttonType: PlainButton }
|
||||
-- , { icon: apIcon, buttonType: HighlightedButton }
|
||||
-- , { icon: appendIcon, buttonType: PlainButton }
|
||||
-- , { icon: applyflippedIcon, buttonType: PlainButton }
|
||||
-- , { icon: applyIcon, buttonType: PlainButton }
|
||||
-- , { icon: bindIcon, buttonType: PlainButton }
|
||||
-- , { icon: composeIcon, buttonType: PlainButton }
|
||||
-- , { icon: forallIcon, buttonType: PlainButton }
|
||||
-- , { icon: kleisliIcon, buttonType: DisabledButton }
|
||||
-- , { icon: mapflippedIcon, buttonType: PlainButton }
|
||||
-- , { icon: mapIcon, buttonType: PlainButton }
|
||||
-- , { icon: pslogoIcon, buttonType: PlainButton }
|
||||
-- ]
|
||||
-- add "Icon Button" mkIconButton
|
||||
-- [ { icon: alternativeIcon, buttonType: PlainButton }
|
||||
-- , { icon: apIcon, buttonType: HighlightedButton }
|
||||
-- , { icon: appendIcon, buttonType: PlainButton }
|
||||
-- , { icon: applyflippedIcon, buttonType: PlainButton }
|
||||
-- , { icon: applyIcon, buttonType: PlainButton }
|
||||
-- , { icon: bindIcon, buttonType: PlainButton }
|
||||
-- , { icon: composeIcon, buttonType: PlainButton }
|
||||
-- , { icon: forallIcon, buttonType: PlainButton }
|
||||
-- , { icon: kleisliIcon, buttonType: DisabledButton }
|
||||
-- , { icon: mapflippedIcon, buttonType: PlainButton }
|
||||
-- , { icon: mapIcon, buttonType: PlainButton }
|
||||
-- , { icon: pslogoIcon, buttonType: PlainButton }
|
||||
-- ]
|
||||
where
|
||||
mkExample = do
|
||||
button <- mkButton
|
||||
component "ExampleButton" \{ text, buttonType, buttonProps } -> React.do
|
||||
pure
|
||||
$ element button
|
||||
{ children: [ R.text text ], buttonProps, buttonType
|
||||
{ kids: [ R.text text ]
|
||||
, buttonProps
|
||||
, buttonType
|
||||
, className: ""
|
||||
}
|
||||
|
||||
-- mkIconButton = do
|
||||
-- button <- mkButton
|
||||
-- component "ExampleIconButton" \{ icon, buttonType } -> React.do
|
||||
-- pure
|
||||
-- $ element button
|
||||
-- { children: [ element icon { width: 30 } ]
|
||||
-- , buttonProps: { }
|
||||
-- , buttonType
|
||||
-- }
|
||||
|
||||
-- mkIconButton = do
|
||||
-- button <- mkButton
|
||||
-- component "ExampleIconButton" \{ icon, buttonType } -> React.do
|
||||
-- pure
|
||||
-- $ element button
|
||||
-- { children: [ element icon { width: 30 } ]
|
||||
-- , buttonProps: { }
|
||||
-- , buttonType
|
||||
-- }
|
||||
loremIpsum ∷ String
|
||||
loremIpsum =
|
||||
"""PureScript is a strongly-typed, purely-functional programming language that compiles"""
|
||||
|
@ -1,7 +1,6 @@
|
||||
module CardStories where
|
||||
|
||||
import Prelude hiding (add)
|
||||
|
||||
import Card.Component (mkCard, mkCardContent, mkCardSubtitle, mkCardTitle)
|
||||
import Decorator.FullScreen (fullScreenDecorator)
|
||||
import Effect (Effect)
|
||||
@ -32,13 +31,14 @@ stories = do
|
||||
{ children:
|
||||
pure
|
||||
$ element card
|
||||
{ children:
|
||||
[ element cardTitle { children: [ R.text title ] }
|
||||
, element cardSubtitle { children: [ R.text subtitle ] }
|
||||
, element cardContent { children: [ content ] }
|
||||
{ kids:
|
||||
[ element cardTitle { kids: [ R.text title ] }
|
||||
, element cardSubtitle { kids: [ R.text subtitle ] }
|
||||
, element cardContent { kids: [ content ] }
|
||||
]
|
||||
, className: ""
|
||||
}
|
||||
, style: css { width: "400px" }
|
||||
, style: css { width: "400px", padding: "60px", overflow: "hidden" }
|
||||
}
|
||||
|
||||
loremIpsum ∷ String
|
||||
|
@ -23,6 +23,9 @@ import Theme.Types (CSSTheme)
|
||||
import Web.HTML (window)
|
||||
import Web.HTML.Window (localStorage)
|
||||
import Web.Storage.Storage (getItem, setItem)
|
||||
import Yoga.Font as Font
|
||||
import Yoga.Font.PragmataPro as PragmataPro
|
||||
import Yoga.Font.Rubik as Rubik
|
||||
|
||||
fullScreenDecorator ∷ Effect JSX -> Effect JSX
|
||||
fullScreenDecorator mkChild = do
|
||||
@ -41,7 +44,7 @@ fullScreenDecorator mkChild = do
|
||||
}
|
||||
, children:
|
||||
[ element themeSwitcher
|
||||
{ children: [ child ]
|
||||
{ kids: [ child ]
|
||||
, defaultTheme: { name: "Dark", theme: dark }
|
||||
, themes:
|
||||
[ { name: "Dark", theme: dark }
|
||||
@ -59,7 +62,7 @@ type DefaultTheme
|
||||
|
||||
mkThemeSwitcher ∷
|
||||
Effect
|
||||
( ReactComponent { defaultTheme ∷ DefaultTheme, themes ∷ Array DefaultTheme, children ∷ Array JSX }
|
||||
( ReactComponent { defaultTheme ∷ DefaultTheme, themes ∷ Array DefaultTheme, kids ∷ Array JSX }
|
||||
)
|
||||
mkThemeSwitcher = do
|
||||
themeProvider <- mkThemeProvider
|
||||
@ -72,10 +75,11 @@ mkThemeSwitcher = do
|
||||
, top: 10
|
||||
, right: 10
|
||||
}
|
||||
, "@font-face": Font.arrayToCss (Rubik.fontFamilies <> [ PragmataPro.fontFamily ])
|
||||
}
|
||||
storage <- window >>= localStorage
|
||||
saved ∷ (Maybe DefaultTheme) <- getItem "theme" storage <#> (_ >>= readJSON_)
|
||||
component "ThemeSwitcher" \{ defaultTheme, themes, children } -> React.do
|
||||
component "ThemeSwitcher" \{ defaultTheme, themes, kids } -> React.do
|
||||
classes <- useStyles
|
||||
{ theme, name } /\ modTheme <- useState $ fromMaybe defaultTheme saved
|
||||
let
|
||||
@ -109,7 +113,7 @@ mkThemeSwitcher = do
|
||||
[ R.div
|
||||
{ style: css { backgroundColor: theme.backgroundColour, width: "100%", height: "100%" }
|
||||
, children:
|
||||
[ themeSelect ] <> children
|
||||
[ themeSelect ] <> kids
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import Prelude hiding (add)
|
||||
import CompileEditor.Component (mkCompileEditor)
|
||||
import Decorator.FullScreen (fullScreenDecorator)
|
||||
import Effect (Effect)
|
||||
import Milkis.Impl.Window (windowFetch)
|
||||
import Storybook.React (Storybook, add, addDecorator, storiesOf)
|
||||
|
||||
initialCode :: String
|
||||
@ -13,12 +14,14 @@ initialCode =
|
||||
import Batteries
|
||||
|
||||
main :: Effect Unit
|
||||
main ="""
|
||||
main = log "Hi, there""""
|
||||
|
||||
stories ∷ Effect Storybook
|
||||
stories = do
|
||||
storiesOf "Editor" do
|
||||
addDecorator fullScreenDecorator
|
||||
add "The Editor" mkCompileEditor
|
||||
[ { initialCode }
|
||||
add "The Editor" (mkCompileEditor windowFetch)
|
||||
[ { initialCode
|
||||
, height: "300px"
|
||||
}
|
||||
]
|
||||
|
@ -1,31 +1,33 @@
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
const path = require('path');
|
||||
const path = require("path");
|
||||
const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin");
|
||||
|
||||
const isWebpackDevServer = process.argv.some(a => path.basename(a) === 'webpack-dev-server');
|
||||
const isWebpackDevServer = process.argv.some(
|
||||
a => path.basename(a) === "webpack-dev-server"
|
||||
);
|
||||
|
||||
const isWatch = process.argv.some(a => a === '--watch');
|
||||
const isWatch = process.argv.some(a => a === "--watch");
|
||||
|
||||
module.exports = {
|
||||
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: 'bundle.js'
|
||||
path: path.resolve(__dirname, "dist"),
|
||||
filename: "bundle.js"
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new MonacoWebpackPlugin({
|
||||
languages: ["json"]
|
||||
})
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.purs$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'purs-loader',
|
||||
loader: "purs-loader",
|
||||
options: {
|
||||
src: [
|
||||
'src/**/*.purs',
|
||||
'test/**/*.purs',
|
||||
'stories/**/*.purs',
|
||||
],
|
||||
src: ["src/**/*.purs", "test/**/*.purs", "stories/**/*.purs"],
|
||||
spago: true,
|
||||
watch: isWebpackDevServer || isWatch,
|
||||
pscIde: true
|
||||
@ -35,29 +37,32 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
test: /\.css$/i,
|
||||
use: ['style-loader', 'css-loader'],
|
||||
use: ["style-loader", "css-loader"]
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpg|gif)$/i,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
loader: "url-loader",
|
||||
options: {
|
||||
limit: 8192,
|
||||
},
|
||||
},
|
||||
],
|
||||
limit: 8192
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.svg$/,
|
||||
loader: 'react-svg-loader'
|
||||
loader: "react-svg-loader"
|
||||
},
|
||||
{
|
||||
test: /\.(woff|woff2|eot|ttf|otf)$/,
|
||||
use: ["file-loader"]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
resolve: {
|
||||
modules: [ 'node_modules' ],
|
||||
extensions: [ '.purs', '.js']
|
||||
modules: ["node_modules"],
|
||||
extensions: [".purs", ".js"]
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -126,41 +126,42 @@ let overrides = {=}
|
||||
let additions =
|
||||
{ react-testing-library =
|
||||
{ dependencies =
|
||||
[ "aff-promise"
|
||||
, "console"
|
||||
, "debug"
|
||||
, "effect"
|
||||
, "foreign"
|
||||
, "foreign-object"
|
||||
, "psci-support"
|
||||
, "react-basic-hooks"
|
||||
, "remotedata"
|
||||
, "run"
|
||||
, "simple-json"
|
||||
, "spec"
|
||||
, "spec-discovery"
|
||||
]
|
||||
[ "aff-promise"
|
||||
, "console"
|
||||
, "debug"
|
||||
, "effect"
|
||||
, "foreign"
|
||||
, "foreign-object"
|
||||
, "psci-support"
|
||||
, "react-basic-hooks"
|
||||
, "remotedata"
|
||||
, "run"
|
||||
, "simple-json"
|
||||
, "spec"
|
||||
, "spec-discovery"
|
||||
]
|
||||
, repo =
|
||||
"https://github.com/i-am-the-slime/purescript-react-testing-library.git"
|
||||
, version = "b872928414a887ccefbe857038af4e57227dad16"
|
||||
}
|
||||
, pseudo-random =
|
||||
{ dependencies =
|
||||
[ "prelude", "console", "effect", "lcg", "arrays", "st" ]
|
||||
[ "prelude", "console", "effect", "lcg", "arrays", "st" ]
|
||||
, repo = "https://github.com/opyapeus/purescript-pseudo-random.git"
|
||||
, version = "7715e8a2c096c480a093a5e0a6df1ece4df5ed2a"
|
||||
}
|
||||
, matryoshka =
|
||||
{ dependencies =
|
||||
[ "prelude"
|
||||
, "fixed-points"
|
||||
, "free"
|
||||
, "transformers"
|
||||
, "profunctor"
|
||||
]
|
||||
[ "prelude", "fixed-points", "free", "transformers", "profunctor" ]
|
||||
, repo = "https://github.com/slamdata/purescript-matryoshka.git"
|
||||
, version = "caaca2d836d52159ba7963333996286a00428394"
|
||||
}
|
||||
, interpolate =
|
||||
{ dependencies = [ "prelude" ]
|
||||
, repo =
|
||||
"https://github.com/jordanmartinez/purescript-interpolate.git"
|
||||
, version = "v2.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
in upstream // overrides // additions
|
||||
in upstream ⫽ overrides ⫽ additions
|
||||
|