initial commit
This commit is contained in:
commit
2b7bb08034
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
.DS_Store
|
||||||
|
/target
|
||||||
|
/classes
|
||||||
|
/checkouts
|
||||||
|
pom.xml
|
||||||
|
pom.xml.asc
|
||||||
|
*.jar
|
||||||
|
*.class
|
||||||
|
/.lein-*
|
||||||
|
/.nrepl-port
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2016 Gered King
|
||||||
|
|
||||||
|
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.
|
182
README.md
Normal file
182
README.md
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
# electroncljs
|
||||||
|
|
||||||
|
A Leiningen template for [Electron](http://electron.atom.io/)
|
||||||
|
applications written using ClojureScript, Figwheel and Reagent.
|
||||||
|
|
||||||
|
This template is based on [descjop](https://github.com/karad/lein_template_descjop).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
$ lein new electroncljs <your-project-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
Then,
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cd <your-project-name>/
|
||||||
|
$ lein npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
This will download all the required NPM dependencies necessary.
|
||||||
|
|
||||||
|
Once complete you can get to work on your app.
|
||||||
|
|
||||||
|
## Getting Started With Electron App Development
|
||||||
|
|
||||||
|
I **strongly** recommend first reading the [Quick Start Guide](http://electron.atom.io/docs/tutorial/quick-start/)
|
||||||
|
on the Electron website before continuing further! At least up until it
|
||||||
|
starts talking about running/packaging your app, as that part is
|
||||||
|
different here.
|
||||||
|
|
||||||
|
## Project Layout
|
||||||
|
|
||||||
|
#### `/app`
|
||||||
|
|
||||||
|
The main Electron app directory. Everything in here is what will be
|
||||||
|
available to your app when it is running and will be included with your
|
||||||
|
app when packaged for distribution.
|
||||||
|
|
||||||
|
You should place your app resources here such as images, CSS, other JS
|
||||||
|
scripts, etc.
|
||||||
|
|
||||||
|
`index.html` is what will be loaded first when your application starts.
|
||||||
|
|
||||||
|
`package.json` is used by Electron to specify details about your
|
||||||
|
application and most importantly what the startup script is. You
|
||||||
|
probably won't need to change this other then updating the application
|
||||||
|
name and version as needed.
|
||||||
|
|
||||||
|
#### `/src`
|
||||||
|
|
||||||
|
Common source directory that will be available to both the Electron
|
||||||
|
main process code and the renderer process code. You can also think of
|
||||||
|
this as where you'd put your `.cljc` files if this were a typical
|
||||||
|
Clojure/ClojureScript web app.
|
||||||
|
|
||||||
|
#### `/src_front`
|
||||||
|
|
||||||
|
Source root for the Electron renderer process code. This is likely
|
||||||
|
where the vast majority of your application code will go.
|
||||||
|
|
||||||
|
#### `/src_main`
|
||||||
|
|
||||||
|
Source root for the Electron main process code.
|
||||||
|
|
||||||
|
#### `/env`
|
||||||
|
|
||||||
|
Additional source roots for `/src`, `/src_front`, and `/src_main` which
|
||||||
|
are pulled in for either development or production builds.
|
||||||
|
|
||||||
|
There is also an application config map located under
|
||||||
|
`/env/[profile]/src/[your-project-name]/config.cljs`
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
To build both the code for the main and renderer process:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ lein build
|
||||||
|
```
|
||||||
|
|
||||||
|
Or to build each separately:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ lein build-main
|
||||||
|
$ lein build-front
|
||||||
|
```
|
||||||
|
|
||||||
|
JS artifacts will be output to `/app/js`.
|
||||||
|
|
||||||
|
To clean up all build artifacts:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ lein clean
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running
|
||||||
|
|
||||||
|
After building, simply do:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ lein run
|
||||||
|
```
|
||||||
|
|
||||||
|
And Electron should start up with your app running.
|
||||||
|
|
||||||
|
## Figwheel
|
||||||
|
|
||||||
|
IMPORTANT: You should start up Figwheel **before** Electron is running!
|
||||||
|
|
||||||
|
```
|
||||||
|
$ lein figwheel
|
||||||
|
```
|
||||||
|
|
||||||
|
And then in another terminal:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ lein run
|
||||||
|
```
|
||||||
|
|
||||||
|
By default `lein figwheel` will run for the Electron renderer process
|
||||||
|
code which is probably what you will want the majority of the time.
|
||||||
|
|
||||||
|
You can connect to the Figwheel REPL on port 7888. Once connected if
|
||||||
|
you run:
|
||||||
|
|
||||||
|
```
|
||||||
|
(cljs-repl)
|
||||||
|
```
|
||||||
|
|
||||||
|
You are now set up to work with your renderer process application code.
|
||||||
|
|
||||||
|
Note that you can also use Figwheel for the Electron main process, but
|
||||||
|
do keep in mind that each time you make a code change Electron will
|
||||||
|
restart to make sure _all_ potential main process code changes are
|
||||||
|
reloaded.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ lein figwheel main
|
||||||
|
```
|
||||||
|
|
||||||
|
You can change this reload behaviour if you need to by editing the
|
||||||
|
function `on-figwheel-reload!` located under
|
||||||
|
`/env/dev/src_main/[your-project-name]/main/init.cljs`. If you do change
|
||||||
|
this, just remember that certain code changes won't take effect until
|
||||||
|
Electron relaunches.
|
||||||
|
|
||||||
|
## Packaging for Release
|
||||||
|
|
||||||
|
Out of the box, you can do:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ lein package
|
||||||
|
```
|
||||||
|
|
||||||
|
Which will prepare an Electron release for your app under `/releases`.
|
||||||
|
Note that with the default `project.clj` configuration, this will only
|
||||||
|
build a release for the current platform/architecture.
|
||||||
|
|
||||||
|
You can add additional platform/architectures and change other
|
||||||
|
packaging properties by editing the `package` alias in `project.clj`.
|
||||||
|
|
||||||
|
For example, to build for all platforms (Win/Linux/Mac):
|
||||||
|
|
||||||
|
```
|
||||||
|
["with-profile" "prod" "shell" "./node_modules/.bin/electron-packager"
|
||||||
|
"app" :project/name
|
||||||
|
~(str "--version=" electron-version)
|
||||||
|
"--asar"
|
||||||
|
"--out=releases"
|
||||||
|
"--overwrite"
|
||||||
|
"--platform=all"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Building Windows releases under Mac/Linux is supported but you will
|
||||||
|
need to install Wine.
|
||||||
|
|
||||||
|
Packaging is performed via [electron-packager](https://www.npmjs.com/package/electron-packager).
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Distributed under the the MIT License. See LICENSE for more details.
|
6
project.clj
Normal file
6
project.clj
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
(defproject electroncljs/lein-template "0.1"
|
||||||
|
:description "Leiningen template for creating Electron apps with ClojureScript"
|
||||||
|
:url "https://github.com/gered/electroncljs"
|
||||||
|
:license {:name "MIT License"
|
||||||
|
:url "http://opensource.org/licenses/MIT"}
|
||||||
|
:eval-in-leiningen true)
|
13
resources/leiningen/new/electroncljs/.gitignore
vendored
Normal file
13
resources/leiningen/new/electroncljs/.gitignore
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
.DS_Store
|
||||||
|
/target
|
||||||
|
/classes
|
||||||
|
/checkouts
|
||||||
|
pom.xml
|
||||||
|
pom.xml.asc
|
||||||
|
*.jar
|
||||||
|
*.class
|
||||||
|
/.lein-*
|
||||||
|
/.nrepl-port
|
||||||
|
/node_modules
|
||||||
|
/releases
|
||||||
|
/*.log
|
21
resources/leiningen/new/electroncljs/LICENSE
Normal file
21
resources/leiningen/new/electroncljs/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) {{year}} YOUR-NAME-HERE
|
||||||
|
|
||||||
|
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.
|
12
resources/leiningen/new/electroncljs/README.md
Normal file
12
resources/leiningen/new/electroncljs/README.md
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# {{name}}
|
||||||
|
|
||||||
|
A ClojureScript Electron application designed to ... well, that part is
|
||||||
|
up to you.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
FIXME
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Distributed under the the MIT License. See LICENSE for more details.
|
558
resources/leiningen/new/electroncljs/app/css/todos.css
Normal file
558
resources/leiningen/new/electroncljs/app/css/todos.css
Normal file
|
@ -0,0 +1,558 @@
|
||||||
|
@charset "utf-8";
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
background: none;
|
||||||
|
font-size: 100%;
|
||||||
|
vertical-align: baseline;
|
||||||
|
font-family: inherit;
|
||||||
|
color: inherit;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-ms-appearance: none;
|
||||||
|
-o-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||||
|
line-height: 1.4em;
|
||||||
|
background: #eaeaea;
|
||||||
|
/* background: #eaeaea url('bg.png'); */
|
||||||
|
color: #4d4d4d;
|
||||||
|
width: 550px;
|
||||||
|
margin: 0 auto;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-font-smoothing: antialiased;
|
||||||
|
-ms-font-smoothing: antialiased;
|
||||||
|
-o-font-smoothing: antialiased;
|
||||||
|
font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
input[type="checkbox"] {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todoapp {
|
||||||
|
background: #fff;
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
margin: 130px 0 40px 0;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
position: relative;
|
||||||
|
border-top-left-radius: 2px;
|
||||||
|
border-top-right-radius: 2px;
|
||||||
|
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
|
||||||
|
0 25px 50px 0 rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
#todoapp:before {
|
||||||
|
content: '';
|
||||||
|
border-left: 1px solid #f5d6d6;
|
||||||
|
border-right: 1px solid #f5d6d6;
|
||||||
|
width: 2px;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 40px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todoapp input::-webkit-input-placeholder {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todoapp input::-moz-placeholder {
|
||||||
|
font-style: italic;
|
||||||
|
color: #a9a9a9;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todoapp h1 {
|
||||||
|
position: absolute;
|
||||||
|
top: -120px;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 70px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
color: #b3b3b3;
|
||||||
|
color: rgba(255, 255, 255, 0.3);
|
||||||
|
text-shadow: -1px -1px rgba(0, 0, 0, 0.2);
|
||||||
|
-webkit-text-rendering: optimizeLegibility;
|
||||||
|
-moz-text-rendering: optimizeLegibility;
|
||||||
|
-ms-text-rendering: optimizeLegibility;
|
||||||
|
-o-text-rendering: optimizeLegibility;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header {
|
||||||
|
padding-top: 15px;
|
||||||
|
border-radius: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header:before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 15px;
|
||||||
|
z-index: 2;
|
||||||
|
border-bottom: 1px solid #6c615c;
|
||||||
|
background: #8d7d77;
|
||||||
|
background: -webkit-gradient(linear, left top, left bottom, from(rgba(132, 110, 100, 0.8)),to(rgba(101, 84, 76, 0.8)));
|
||||||
|
background: -webkit-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
|
||||||
|
background: linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
|
||||||
|
/* filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670'); */
|
||||||
|
border-top-left-radius: 1px;
|
||||||
|
border-top-right-radius: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#new-todo,
|
||||||
|
.edit {
|
||||||
|
position: relative;
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 24px;
|
||||||
|
font-family: inherit;
|
||||||
|
line-height: 1.4em;
|
||||||
|
border: 0;
|
||||||
|
outline: none;
|
||||||
|
color: inherit;
|
||||||
|
padding: 6px;
|
||||||
|
border: 1px solid #999;
|
||||||
|
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
-ms-box-sizing: border-box;
|
||||||
|
-o-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-font-smoothing: antialiased;
|
||||||
|
-ms-font-smoothing: antialiased;
|
||||||
|
-o-font-smoothing: antialiased;
|
||||||
|
font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
#new-todo {
|
||||||
|
padding: 16px 16px 16px 60px;
|
||||||
|
border: none;
|
||||||
|
background: rgba(0, 0, 0, 0.02);
|
||||||
|
z-index: 2;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
border-top: 1px dotted #adadad;
|
||||||
|
}
|
||||||
|
|
||||||
|
label[for='toggle-all'] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toggle-all {
|
||||||
|
position: absolute;
|
||||||
|
top: -42px;
|
||||||
|
left: -4px;
|
||||||
|
width: 40px;
|
||||||
|
text-align: center;
|
||||||
|
/* Mobile Safari */
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toggle-all:before {
|
||||||
|
content: '»';
|
||||||
|
font-size: 28px;
|
||||||
|
color: #d9d9d9;
|
||||||
|
padding: 0 25px 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toggle-all:checked:before {
|
||||||
|
color: #737373;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-list {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-list li {
|
||||||
|
position: relative;
|
||||||
|
font-size: 24px;
|
||||||
|
border-bottom: 1px dotted #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-list li:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-list li.editing {
|
||||||
|
border-bottom: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-list li.editing .edit {
|
||||||
|
display: block;
|
||||||
|
width: 506px;
|
||||||
|
padding: 13px 17px 12px 17px;
|
||||||
|
margin: 0 0 0 43px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-list li.editing .view {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-list li .toggle {
|
||||||
|
text-align: center;
|
||||||
|
width: 40px;
|
||||||
|
/* auto, since non-WebKit browsers doesn't support input styling */
|
||||||
|
height: auto;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
margin: auto 0;
|
||||||
|
/* Mobile Safari */
|
||||||
|
border: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-ms-appearance: none;
|
||||||
|
-o-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-list li .toggle:after {
|
||||||
|
content: '✔';
|
||||||
|
/* 40 + a couple of pixels visual adjustment */
|
||||||
|
line-height: 43px;
|
||||||
|
font-size: 20px;
|
||||||
|
color: #d9d9d9;
|
||||||
|
text-shadow: 0 -1px 0 #bfbfbf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-list li .toggle:checked:after {
|
||||||
|
color: #85ada7;
|
||||||
|
text-shadow: 0 1px 0 #669991;
|
||||||
|
bottom: 1px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-list li label {
|
||||||
|
white-space: pre;
|
||||||
|
word-break: break-word;
|
||||||
|
padding: 15px 60px 15px 15px;
|
||||||
|
margin-left: 45px;
|
||||||
|
display: block;
|
||||||
|
line-height: 1.2;
|
||||||
|
-webkit-transition: color 0.4s;
|
||||||
|
transition: color 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-list li.completed label {
|
||||||
|
color: #a9a9a9;
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-list li .destroy {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 10px;
|
||||||
|
bottom: 0;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
margin: auto 0;
|
||||||
|
font-size: 22px;
|
||||||
|
color: #a88a8a;
|
||||||
|
-webkit-transition: all 0.2s;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-list li .destroy:hover {
|
||||||
|
text-shadow: 0 0 1px #000,
|
||||||
|
0 0 10px rgba(199, 107, 107, 0.8);
|
||||||
|
-webkit-transform: scale(1.3);
|
||||||
|
-ms-transform: scale(1.3);
|
||||||
|
transform: scale(1.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-list li .destroy:after {
|
||||||
|
content: '✖';
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-list li:hover .destroy {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-list li .edit {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-list li.editing:last-child {
|
||||||
|
margin-bottom: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
color: #777;
|
||||||
|
padding: 0 15px;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: -31px;
|
||||||
|
left: 0;
|
||||||
|
height: 20px;
|
||||||
|
z-index: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer:before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 31px;
|
||||||
|
left: 0;
|
||||||
|
height: 50px;
|
||||||
|
z-index: -1;
|
||||||
|
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3),
|
||||||
|
0 6px 0 -3px rgba(255, 255, 255, 0.8),
|
||||||
|
0 7px 1px -3px rgba(0, 0, 0, 0.3),
|
||||||
|
0 43px 0 -6px rgba(255, 255, 255, 0.8),
|
||||||
|
0 44px 2px -6px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-count {
|
||||||
|
float: left;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#filters {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#filters li {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#filters li a {
|
||||||
|
color: #83756f;
|
||||||
|
margin: 2px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#filters li a.selected {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#clear-completed {
|
||||||
|
float: right;
|
||||||
|
position: relative;
|
||||||
|
line-height: 20px;
|
||||||
|
text-decoration: none;
|
||||||
|
background: rgba(0, 0, 0, 0.1);
|
||||||
|
font-size: 11px;
|
||||||
|
padding: 0 10px;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#clear-completed:hover {
|
||||||
|
background: rgba(0, 0, 0, 0.15);
|
||||||
|
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#info {
|
||||||
|
margin: 65px auto 0;
|
||||||
|
color: #a6a6a6;
|
||||||
|
font-size: 12px;
|
||||||
|
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#info a {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Hack to remove background from Mobile Safari.
|
||||||
|
Can't use it globally since it destroys checkboxes in Firefox and Opera
|
||||||
|
*/
|
||||||
|
|
||||||
|
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||||
|
#toggle-all,
|
||||||
|
#todo-list li .toggle {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#todo-list li .toggle {
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#toggle-all {
|
||||||
|
top: -56px;
|
||||||
|
left: -15px;
|
||||||
|
width: 65px;
|
||||||
|
height: 41px;
|
||||||
|
-webkit-transform: rotate(90deg);
|
||||||
|
-ms-transform: rotate(90deg);
|
||||||
|
transform: rotate(90deg);
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
margin: 20px 0;
|
||||||
|
border: 0;
|
||||||
|
border-top: 1px dashed #C5C5C5;
|
||||||
|
border-bottom: 1px dashed #F7F7F7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.learn a {
|
||||||
|
font-weight: normal;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #b83f45;
|
||||||
|
}
|
||||||
|
|
||||||
|
.learn a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: #787e7e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.learn h3,
|
||||||
|
.learn h4,
|
||||||
|
.learn h5 {
|
||||||
|
margin: 10px 0;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.2;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.learn h3 {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.learn h4 {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.learn h5 {
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.learn ul {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 0 30px 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.learn li {
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.learn p {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 300;
|
||||||
|
line-height: 1.3;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quote {
|
||||||
|
border: none;
|
||||||
|
margin: 20px 0 60px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quote p {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quote p:before {
|
||||||
|
content: '“';
|
||||||
|
font-size: 50px;
|
||||||
|
opacity: .15;
|
||||||
|
position: absolute;
|
||||||
|
top: -20px;
|
||||||
|
left: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quote p:after {
|
||||||
|
content: '”';
|
||||||
|
font-size: 50px;
|
||||||
|
opacity: .15;
|
||||||
|
position: absolute;
|
||||||
|
bottom: -42px;
|
||||||
|
right: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quote footer {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -40px;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quote footer img {
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quote footer a {
|
||||||
|
margin-left: 5px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.speech-bubble {
|
||||||
|
position: relative;
|
||||||
|
padding: 10px;
|
||||||
|
background: rgba(0, 0, 0, .04);
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.speech-bubble:after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
right: 30px;
|
||||||
|
border: 13px solid transparent;
|
||||||
|
border-top-color: rgba(0, 0, 0, .04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.learn-bar > .learn {
|
||||||
|
position: absolute;
|
||||||
|
width: 272px;
|
||||||
|
top: 8px;
|
||||||
|
left: -300px;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: rgba(255, 255, 255, .6);
|
||||||
|
-webkit-transition-property: left;
|
||||||
|
transition-property: left;
|
||||||
|
-webkit-transition-duration: 500ms;
|
||||||
|
transition-duration: 500ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 899px) {
|
||||||
|
.learn-bar {
|
||||||
|
width: auto;
|
||||||
|
margin: 0 0 0 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.learn-bar > .learn {
|
||||||
|
left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.learn-bar #todoapp {
|
||||||
|
width: 550px;
|
||||||
|
margin: 130px auto 40px auto;
|
||||||
|
}
|
||||||
|
}
|
15
resources/leiningen/new/electroncljs/app/index.html
Normal file
15
resources/leiningen/new/electroncljs/app/index.html
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{{=<% %>=}}
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title><%name%></title>
|
||||||
|
<link rel="stylesheet" href="css/todos.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app">
|
||||||
|
<h1>Reagent has not loaded yet.</h1>
|
||||||
|
</div>
|
||||||
|
<script src="js/front.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
6
resources/leiningen/new/electroncljs/app/package.json
Normal file
6
resources/leiningen/new/electroncljs/app/package.json
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{{=<% %>=}}
|
||||||
|
{
|
||||||
|
"name": "<%name%>",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"main": "js/main.js"
|
||||||
|
}
|
8
resources/leiningen/new/electroncljs/env/dev/src/root_ns/config.cljs
vendored
Normal file
8
resources/leiningen/new/electroncljs/env/dev/src/root_ns/config.cljs
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
(ns {{root-ns}}.config)
|
||||||
|
|
||||||
|
(def config
|
||||||
|
{:env :dev
|
||||||
|
:dev-tools {:auto-open? false
|
||||||
|
:position "bottom"}
|
||||||
|
:browser-window {:width 1024
|
||||||
|
:height 768}})
|
2
resources/leiningen/new/electroncljs/env/dev/src/user.clj
vendored
Normal file
2
resources/leiningen/new/electroncljs/env/dev/src/user.clj
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
(ns user
|
||||||
|
(:use figwheel-sidecar.repl-api))
|
11
resources/leiningen/new/electroncljs/env/dev/src_front/root_ns/init.cljs
vendored
Normal file
11
resources/leiningen/new/electroncljs/env/dev/src_front/root_ns/init.cljs
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
(ns {{root-ns}}.init
|
||||||
|
(:require
|
||||||
|
[{{root-ns}}.core :as core]))
|
||||||
|
|
||||||
|
(enable-console-print!)
|
||||||
|
|
||||||
|
(defn start-front!
|
||||||
|
[]
|
||||||
|
(core/init!))
|
||||||
|
|
||||||
|
(start-front!)
|
19
resources/leiningen/new/electroncljs/env/dev/src_main/root_ns/main/init.cljs
vendored
Normal file
19
resources/leiningen/new/electroncljs/env/dev/src_main/root_ns/main/init.cljs
vendored
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
(ns {{root-ns}}.main.init
|
||||||
|
(:require
|
||||||
|
[cljs.nodejs :as nodejs]
|
||||||
|
[{{root-ns}}.main.core :as core]))
|
||||||
|
|
||||||
|
(nodejs/enable-util-print!)
|
||||||
|
|
||||||
|
(def on-figwheel-reload!
|
||||||
|
(fn []
|
||||||
|
(println "Figwheel initiated application reload.")
|
||||||
|
(.relaunch core/app)
|
||||||
|
(.exit core/app 0)))
|
||||||
|
|
||||||
|
(def start-electron!
|
||||||
|
(fn []
|
||||||
|
(reset! core/window nil)
|
||||||
|
(core/init!)))
|
||||||
|
|
||||||
|
(set! *main-cli-fn* start-electron!)
|
6
resources/leiningen/new/electroncljs/env/prod/src/root_ns/config.cljs
vendored
Normal file
6
resources/leiningen/new/electroncljs/env/prod/src/root_ns/config.cljs
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
(ns {{root-ns}}.config)
|
||||||
|
|
||||||
|
(def config
|
||||||
|
{:env :prod
|
||||||
|
:browser-window {:width 1024
|
||||||
|
:height 768}})
|
11
resources/leiningen/new/electroncljs/env/prod/src_front/root_ns/init.cljs
vendored
Normal file
11
resources/leiningen/new/electroncljs/env/prod/src_front/root_ns/init.cljs
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
(ns {{root-ns}}.init
|
||||||
|
(:require
|
||||||
|
[{{root-ns}}.core :as core]))
|
||||||
|
|
||||||
|
(enable-console-print!)
|
||||||
|
|
||||||
|
(defn start-front!
|
||||||
|
[]
|
||||||
|
(core/init!))
|
||||||
|
|
||||||
|
(start-front!)
|
13
resources/leiningen/new/electroncljs/env/prod/src_main/root_ns/main/init.cljs
vendored
Normal file
13
resources/leiningen/new/electroncljs/env/prod/src_main/root_ns/main/init.cljs
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
(ns {{root-ns}}.main.init
|
||||||
|
(:require
|
||||||
|
[cljs.nodejs :as nodejs]
|
||||||
|
[{{root-ns}}.main.core :as core]))
|
||||||
|
|
||||||
|
(nodejs/enable-util-print!)
|
||||||
|
|
||||||
|
(def start-electron!
|
||||||
|
(fn []
|
||||||
|
(reset! core/window nil)
|
||||||
|
(core/init!)))
|
||||||
|
|
||||||
|
(set! *main-cli-fn* start-electron!)
|
107
resources/leiningen/new/electroncljs/project.clj
Normal file
107
resources/leiningen/new/electroncljs/project.clj
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
(def electron-version "1.4.10")
|
||||||
|
(def figwheel-version "0.5.8")
|
||||||
|
|
||||||
|
(defproject {{name}} "0.1.0-SNAPSHOT"
|
||||||
|
:description "FIXME: write description"
|
||||||
|
:url "http://example.com/FIXME"
|
||||||
|
:license {:name "MIT License"
|
||||||
|
:url "http://opensource.org/licenses/MIT"}
|
||||||
|
|
||||||
|
:dependencies [[cljsjs/bootstrap "3.3.6-1"]
|
||||||
|
[figwheel ~figwheel-version]
|
||||||
|
[org.clojure/clojure "1.8.0"]
|
||||||
|
[org.clojure/clojurescript "1.9.293"]
|
||||||
|
[org.webjars/bootstrap "3.3.6"]
|
||||||
|
[reagent "0.6.0"]
|
||||||
|
[ring/ring-core "1.5.0"]]
|
||||||
|
|
||||||
|
:plugins [[lein-cljsbuild "1.1.4"]
|
||||||
|
[lein-externs "0.1.6"]
|
||||||
|
[lein-figwheel ~figwheel-version]
|
||||||
|
[lein-npm "0.6.2"]
|
||||||
|
[lein-shell "0.5.0"]]
|
||||||
|
|
||||||
|
:npm {:devDependencies [[electron-prebuilt ~electron-version]
|
||||||
|
[electron-packager "^8.3.0"]
|
||||||
|
[closurecompiler-externs "^1.0.4"]
|
||||||
|
[ws "^1.1.1"]]}
|
||||||
|
|
||||||
|
:source-paths ["src"]
|
||||||
|
|
||||||
|
:clean-targets ^{:protect false} [:target-path
|
||||||
|
"releases"
|
||||||
|
[:cljsbuild :builds :main :compiler :output-to]
|
||||||
|
[:cljsbuild :builds :main :compiler :output-dir]
|
||||||
|
[:cljsbuild :builds :front :compiler :output-to]
|
||||||
|
[:cljsbuild :builds :front :compiler :output-dir]
|
||||||
|
"app/js/externs_main.js"
|
||||||
|
"app/js/externs_front.js"]
|
||||||
|
|
||||||
|
:figwheel {:nrepl-port 7888
|
||||||
|
:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]
|
||||||
|
:builds-to-start [:front]}
|
||||||
|
|
||||||
|
:cljsbuild {:builds
|
||||||
|
{:main
|
||||||
|
{:source-paths ["src" "src_main"]
|
||||||
|
:figwheel {:on-jsload {{root-ns}}.main.init/on-figwheel-reload!}
|
||||||
|
:compiler {:main {{root-ns}}.main.init
|
||||||
|
:output-to "app/js/main.js"
|
||||||
|
:output-dir "app/js/out_main"
|
||||||
|
:asset-path "app/js/out_main"
|
||||||
|
:externs ["app/js/externs_main.js"]
|
||||||
|
:target :nodejs
|
||||||
|
:optimizations :none}}
|
||||||
|
:front
|
||||||
|
{:source-paths ["src" "src_front"]
|
||||||
|
:figwheel {:on-jsload {{root-ns}}.init/start-front!}
|
||||||
|
:compiler {:main {{root-ns}}.init
|
||||||
|
:output-to "app/js/front.js"
|
||||||
|
:output-dir "app/js/out_front"
|
||||||
|
:asset-path "js/out_front"
|
||||||
|
:externs ["app/js/externs_front.js"]
|
||||||
|
:optimizations :none}}}}
|
||||||
|
|
||||||
|
:profiles {:dev {:source-paths ["env/dev/src"]
|
||||||
|
:dependencies [[com.cemerick/piggieback "0.2.1"]
|
||||||
|
[figwheel-sidecar ~figwheel-version]]
|
||||||
|
:cljsbuild {:builds
|
||||||
|
{:main {:source-paths ["env/dev/src" "env/dev/src_main"]}
|
||||||
|
:front {:source-paths ["env/dev/src" "env/dev/src_front"]}}}}
|
||||||
|
|
||||||
|
:prod {:source-paths ["env/prod/src"]
|
||||||
|
:cljsbuild {:builds
|
||||||
|
{:main {:source-paths ["env/prod/src" "env/prod/src_main"]
|
||||||
|
:compiler ^:replace
|
||||||
|
{:output-to "app/js/main.js"
|
||||||
|
:externs ["app/js/externs_main.js"]
|
||||||
|
:optimizations :advanced
|
||||||
|
:target :nodejs
|
||||||
|
:pretty-print false}}
|
||||||
|
:front {:source-paths ["env/prod/src" "env/prod/src_front"]
|
||||||
|
:compiler ^:replace
|
||||||
|
{:output-to "app/js/front.js"
|
||||||
|
:externs ["app/js/externs_front.js"]
|
||||||
|
:optimizations :advanced
|
||||||
|
:pretty-print false}}}}}}
|
||||||
|
|
||||||
|
|
||||||
|
:aliases {"build-main" ["do"
|
||||||
|
["externs" "main" "app/js/externs_main.js"]
|
||||||
|
["cljsbuild" "once" "main"]]
|
||||||
|
"build-front" ["do"
|
||||||
|
["externs" "front" "app/js/externs_front.js"]
|
||||||
|
["cljsbuild" "once" "front"]]
|
||||||
|
"build" ["do" "build-main" "build-front"]
|
||||||
|
"run" ["do"
|
||||||
|
["shell" "./node_modules/.bin/electron" "app"]]
|
||||||
|
"package" ["do"
|
||||||
|
"clean"
|
||||||
|
["with-profile" "prod" "build"]
|
||||||
|
["with-profile" "prod" "shell" "./node_modules/.bin/electron-packager"
|
||||||
|
"app" :project/name
|
||||||
|
~(str "--version=" electron-version)
|
||||||
|
"--asar"
|
||||||
|
"--out=releases"
|
||||||
|
"--overwrite"]]}
|
||||||
|
)
|
117
resources/leiningen/new/electroncljs/src_front/root_ns/core.cljs
Normal file
117
resources/leiningen/new/electroncljs/src_front/root_ns/core.cljs
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
(ns {{root-ns}}.core
|
||||||
|
(:require
|
||||||
|
[reagent.core :as r]))
|
||||||
|
|
||||||
|
(defonce todos (r/atom (sorted-map)))
|
||||||
|
|
||||||
|
(defonce counter (r/atom 0))
|
||||||
|
|
||||||
|
(defn add-todo
|
||||||
|
[text]
|
||||||
|
(let [id (swap! counter inc)]
|
||||||
|
(swap! todos assoc id {:id id :title text :done false})))
|
||||||
|
|
||||||
|
(defn toggle [id] (swap! todos update-in [id :done] not))
|
||||||
|
(defn save [id title] (swap! todos assoc-in [id :title] title))
|
||||||
|
(defn delete [id] (swap! todos dissoc id))
|
||||||
|
|
||||||
|
(defn mmap [m f a] (->> m (f a) (into (empty m))))
|
||||||
|
(defn complete-all [v] (swap! todos mmap map #(assoc-in % [1 :done] v)))
|
||||||
|
(defn clear-done [] (swap! todos mmap remove #(get-in % [1 :done])))
|
||||||
|
|
||||||
|
(defonce init (do
|
||||||
|
(add-todo "Rename Cloact to Reagent")
|
||||||
|
(add-todo "Add undo demo")
|
||||||
|
(add-todo "Make all rendering async")
|
||||||
|
(add-todo "Allow any arguments to component functions")
|
||||||
|
(complete-all true)))
|
||||||
|
|
||||||
|
(defn todo-input
|
||||||
|
[{:keys [title on-save on-stop]}]
|
||||||
|
(let [val (r/atom title)
|
||||||
|
stop #(do (reset! val "")
|
||||||
|
(if on-stop (on-stop)))
|
||||||
|
save #(let [v (-> @val str clojure.string/trim)]
|
||||||
|
(if-not (empty? v) (on-save v))
|
||||||
|
(stop))]
|
||||||
|
(fn [{:keys [id class placeholder]}]
|
||||||
|
[:input {:type "text" :value @val
|
||||||
|
:id id :class class :placeholder placeholder
|
||||||
|
:on-blur save
|
||||||
|
:on-change #(reset! val (-> % .-target .-value))
|
||||||
|
:on-key-down #(case (.-which %)
|
||||||
|
13 (save)
|
||||||
|
27 (stop)
|
||||||
|
nil)}])))
|
||||||
|
|
||||||
|
(def todo-edit (with-meta todo-input
|
||||||
|
{:component-did-mount #(.focus (r/dom-node %))}))
|
||||||
|
|
||||||
|
(defn todo-stats
|
||||||
|
[{:keys [filt active done]}]
|
||||||
|
(let [props-for (fn [name]
|
||||||
|
{:class (if (= name @filt) "selected")
|
||||||
|
:on-click #(reset! filt name)})]
|
||||||
|
[:div
|
||||||
|
[:span#todo-count
|
||||||
|
[:strong active] " " (case active 1 "item" "items") " left"]
|
||||||
|
[:ul#filters
|
||||||
|
[:li [:a (props-for :all) "All"]]
|
||||||
|
[:li [:a (props-for :active) "Active"]]
|
||||||
|
[:li [:a (props-for :done) "Completed"]]]
|
||||||
|
(when (pos? done)
|
||||||
|
[:button#clear-completed {:on-click clear-done}
|
||||||
|
"Clear completed " done])]))
|
||||||
|
|
||||||
|
(defn todo-item
|
||||||
|
[]
|
||||||
|
(let [editing (r/atom false)]
|
||||||
|
(fn [{:keys [id done title]}]
|
||||||
|
[:li {:class (str (if done "completed ")
|
||||||
|
(if @editing "editing"))}
|
||||||
|
[:div.view
|
||||||
|
[:input.toggle {:type "checkbox" :checked done
|
||||||
|
:on-change #(toggle id)}]
|
||||||
|
[:label {:on-double-click #(reset! editing true)} title]
|
||||||
|
[:button.destroy {:on-click #(delete id)}]]
|
||||||
|
(when @editing
|
||||||
|
[todo-edit {:class "edit" :title title
|
||||||
|
:on-save #(save id %)
|
||||||
|
:on-stop #(reset! editing false)}])])))
|
||||||
|
|
||||||
|
(defn todo-app
|
||||||
|
[props]
|
||||||
|
(let [filt (r/atom :all)]
|
||||||
|
(fn []
|
||||||
|
(let [items (vals @todos)
|
||||||
|
done (->> items (filter :done) count)
|
||||||
|
active (- (count items) done)]
|
||||||
|
[:div
|
||||||
|
[:section#todoapp
|
||||||
|
[:header#header
|
||||||
|
[:h1 "todos"]
|
||||||
|
[todo-input {:id "new-todo"
|
||||||
|
:placeholder "What needs to be done?"
|
||||||
|
:on-save add-todo}]]
|
||||||
|
(when (-> items count pos?)
|
||||||
|
[:div
|
||||||
|
[:section#main
|
||||||
|
[:input#toggle-all {:type "checkbox" :checked (zero? active)
|
||||||
|
:on-change #(complete-all (pos? active))}]
|
||||||
|
[:label {:for "toggle-all"} "Mark all as complete"]
|
||||||
|
[:ul#todo-list
|
||||||
|
(for [todo (filter (case @filt
|
||||||
|
:active (complement :done)
|
||||||
|
:done :done
|
||||||
|
:all identity) items)]
|
||||||
|
^{:key (:id todo)} [todo-item todo])]]
|
||||||
|
[:footer#footer
|
||||||
|
[todo-stats {:active active :done done :filt filt}]]])]
|
||||||
|
[:footer#info
|
||||||
|
[:p "Double-click to edit a todo"]]]))))
|
||||||
|
|
||||||
|
(defn init!
|
||||||
|
[]
|
||||||
|
(r/render
|
||||||
|
[todo-app]
|
||||||
|
(.getElementById js/document "app")))
|
|
@ -0,0 +1,54 @@
|
||||||
|
(ns {{root-ns}}.main.core
|
||||||
|
(:require
|
||||||
|
[cljs.nodejs :as nodejs]
|
||||||
|
[{{root-ns}}.config :refer [config]]))
|
||||||
|
|
||||||
|
(def path (nodejs/require "path"))
|
||||||
|
(def electron (nodejs/require "electron"))
|
||||||
|
(def app (.-app electron))
|
||||||
|
|
||||||
|
(def BrowserWindow (.-BrowserWindow electron))
|
||||||
|
|
||||||
|
(defonce window (atom nil))
|
||||||
|
|
||||||
|
(defn on-window-closed
|
||||||
|
[]
|
||||||
|
(reset! window nil))
|
||||||
|
|
||||||
|
(defn on-window-ready-to-show
|
||||||
|
[]
|
||||||
|
(.show @window))
|
||||||
|
|
||||||
|
(defn on-process-error
|
||||||
|
[error]
|
||||||
|
(println "ERROR:" error))
|
||||||
|
|
||||||
|
(defn on-app-window-all-closed
|
||||||
|
[]
|
||||||
|
(.quit app))
|
||||||
|
|
||||||
|
(defn on-app-quit
|
||||||
|
[e exit-code]
|
||||||
|
(println "Main process quitting. Exit code:" exit-code))
|
||||||
|
|
||||||
|
(defn on-app-ready
|
||||||
|
[launch-info]
|
||||||
|
(let [window-settings (merge
|
||||||
|
{:show false}
|
||||||
|
(:browser-window config))]
|
||||||
|
(println "App ready.")
|
||||||
|
(reset! window (BrowserWindow. (clj->js window-settings)))
|
||||||
|
(.loadURL @window (str "file://" (.getAppPath app) "/index.html"))
|
||||||
|
(.on @window "ready-to-show" on-window-ready-to-show)
|
||||||
|
(.on @window "closed" on-window-closed)
|
||||||
|
(if (get-in config [:dev-tools :auto-open?])
|
||||||
|
(.openDevTools (.-webContents @window)
|
||||||
|
(clj->js {:mode (get-in config [:dev-tools :position] "right")})))))
|
||||||
|
|
||||||
|
(defn init!
|
||||||
|
[]
|
||||||
|
(println "Main process started, app is starting up.")
|
||||||
|
(.on nodejs/process "error" on-process-error)
|
||||||
|
(.on app "window-all-closed" on-app-window-all-closed)
|
||||||
|
(.on app "quit" on-app-quit)
|
||||||
|
(.on app "ready" on-app-ready))
|
66
src/leiningen/new/electroncljs.clj
Normal file
66
src/leiningen/new/electroncljs.clj
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
(ns leiningen.new.electroncljs
|
||||||
|
(:import
|
||||||
|
[java.util Calendar GregorianCalendar])
|
||||||
|
(:require
|
||||||
|
[leiningen.core.main :as main]
|
||||||
|
[leiningen.new.templates :as t]))
|
||||||
|
|
||||||
|
(def render (t/renderer "electroncljs"))
|
||||||
|
|
||||||
|
(defn electroncljs
|
||||||
|
[name]
|
||||||
|
(let [data {:name name
|
||||||
|
:sanitized (t/sanitize name)
|
||||||
|
:root-ns (t/sanitize-ns name)
|
||||||
|
:root-ns-path (t/name-to-path name)
|
||||||
|
:year (.get (GregorianCalendar.) (Calendar/YEAR))}]
|
||||||
|
(main/info "Creating a new ClojureScript Electron project \"" name "\" ...")
|
||||||
|
(t/->files
|
||||||
|
data
|
||||||
|
"app/js"
|
||||||
|
"app/img"
|
||||||
|
["app/css/todos.css" (render "app/css/todos.css")]
|
||||||
|
["app/index.html" (render "app/index.html" data)]
|
||||||
|
["app/package.json" (render "app/package.json" data)]
|
||||||
|
["env/dev/src/{{root-ns-path}}/config.cljs" (render "env/dev/src/root_ns/config.cljs" data)]
|
||||||
|
["env/dev/src/user.clj" (render "env/dev/src/user.clj" data)]
|
||||||
|
["env/dev/src_front/{{root-ns-path}}/init.cljs" (render "env/dev/src_front/root_ns/init.cljs" data)]
|
||||||
|
["env/dev/src_main/{{root-ns-path}}/main/init.cljs" (render "env/dev/src_main/root_ns/main/init.cljs" data)]
|
||||||
|
|
||||||
|
["env/prod/src/{{root-ns-path}}/config.cljs" (render "env/prod/src/root_ns/config.cljs" data)]
|
||||||
|
["env/prod/src_front/{{root-ns-path}}/init.cljs" (render "env/prod/src_front/root_ns/init.cljs" data)]
|
||||||
|
["env/prod/src_main/{{root-ns-path}}/main/init.cljs" (render "env/prod/src_main/root_ns/main/init.cljs" data)]
|
||||||
|
"src/{{root-ns-path}}"
|
||||||
|
["src_front/{{root-ns-path}}/core.cljs" (render "src_front/root_ns/core.cljs" data)]
|
||||||
|
["src_main/{{root-ns-path}}/main/core.cljs" (render "src_main/root_ns/main/core.cljs" data)]
|
||||||
|
[".gitignore" (render ".gitignore")]
|
||||||
|
["LICENSE" (render "LICENSE" data)]
|
||||||
|
["README.md" (render "README.md" data)]
|
||||||
|
["project.clj" (render "project.clj" data)])
|
||||||
|
(main/info "------------------------------------------------------------------------")
|
||||||
|
(main/info "Your new Electron project is ready! To get started:")
|
||||||
|
(main/info "")
|
||||||
|
(main/info " $ cd" name)
|
||||||
|
(main/info " $ lein npm install")
|
||||||
|
(main/info "")
|
||||||
|
(main/info "You app's code is located in a few places:\n")
|
||||||
|
(main/info " /src - code common to both main and renderer (front)")
|
||||||
|
(main/info " /src_front - code for renderer process (UI)")
|
||||||
|
(main/info " /src_main - code for main process (backend)")
|
||||||
|
(main/info "")
|
||||||
|
(main/info "Build profile-specific sources are located under /env")
|
||||||
|
(main/info "Application code config map at:")
|
||||||
|
(main/info (str " /env/dev/src/" (:root-ns-path data) "/config.cljs"))
|
||||||
|
(main/info (str " /env/prod/src/" (:root-ns-path data) "/config.cljs"))
|
||||||
|
(main/info "")
|
||||||
|
(main/info "Electron app resources (HTML, CSS, JS, etc) are located under /app")
|
||||||
|
(main/info "")
|
||||||
|
(main/info "Build: $ lein build")
|
||||||
|
(main/info "Run: $ lein run")
|
||||||
|
(main/info "Rebuild: $ lein clean && lein build")
|
||||||
|
(main/info "Package: $ lein package")
|
||||||
|
(main/info "Figwheel: (do in order!)")
|
||||||
|
(main/info " (terminal #1) $ lein figwheel")
|
||||||
|
(main/info " (terminal #2) $ lein run")
|
||||||
|
(main/info "(Figwheel REPL running on port 7888, run (cljs-repl) after connecting)")
|
||||||
|
(main/info "------------------------------------------------------------------------")))
|
Reference in a new issue