├── .eslintrc ├── .gitignore ├── .travis.yml ├── LICENSE ├── package.json ├── readme.md └── src ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── apple-touch-icon.png ├── browserconfig.xml ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon.ico ├── index.html ├── index.js ├── manifest.webmanifest ├── mstile-150x150.png ├── safari-pinned-tab.svg ├── styles ├── _sakura.scss ├── _show-console.scss └── app.scss ├── utils └── delayed-click.js └── views ├── add-button.js ├── header-section.js ├── index.js ├── show-console.js └── sub-button.js /.eslintrc: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "parserOptions": { 4 | "ecmaVersion": 8, 5 | "ecmaFeatures": { 6 | "experimentalObjectRestSpread": true, 7 | "jsx": true 8 | }, 9 | "sourceType": "module" 10 | }, 11 | 12 | "env": { 13 | "es6": true, 14 | "node": true 15 | }, 16 | 17 | "plugins": [ 18 | "import", 19 | "node", 20 | "promise", 21 | "standard" 22 | ], 23 | 24 | "globals": { 25 | "document": false, 26 | "navigator": false, 27 | "window": false 28 | }, 29 | 30 | "rules": { 31 | "accessor-pairs": "error", 32 | "arrow-spacing": ["error", { "before": true, "after": true }], 33 | "block-spacing": ["error", "always"], 34 | "brace-style": ["error", "1tbs", { "allowSingleLine": true }], 35 | "camelcase": ["error", { "properties": "never" }], 36 | "comma-dangle": ["error", { 37 | "arrays": "never", 38 | "objects": "never", 39 | "imports": "never", 40 | "exports": "never", 41 | "functions": "never" 42 | }], 43 | "comma-spacing": ["error", { "before": false, "after": true }], 44 | "comma-style": ["error", "last"], 45 | "constructor-super": "error", 46 | "curly": ["error", "multi-line"], 47 | "dot-location": ["error", "property"], 48 | "eol-last": "error", 49 | "eqeqeq": ["error", "always", { "null": "ignore" }], 50 | "func-call-spacing": ["error", "never"], 51 | "generator-star-spacing": ["error", { "before": true, "after": true }], 52 | "handle-callback-err": ["error", "^(err|error)$" ], 53 | "indent": ["error", 2, { "SwitchCase": 1 }], 54 | "key-spacing": ["error", { "beforeColon": false, "afterColon": true }], 55 | "keyword-spacing": ["error", { "before": true, "after": true }], 56 | "new-cap": ["error", { "newIsCap": true, "capIsNew": false }], 57 | "new-parens": "error", 58 | "no-array-constructor": "error", 59 | "no-caller": "error", 60 | "no-class-assign": "error", 61 | "no-compare-neg-zero": "error", 62 | "no-cond-assign": "error", 63 | "no-const-assign": "error", 64 | "no-constant-condition": ["error", { "checkLoops": false }], 65 | "no-control-regex": "error", 66 | "no-debugger": "error", 67 | "no-delete-var": "error", 68 | "no-dupe-args": "error", 69 | "no-dupe-class-members": "error", 70 | "no-dupe-keys": "error", 71 | "no-duplicate-case": "error", 72 | "no-empty-character-class": "error", 73 | "no-empty-pattern": "error", 74 | "no-eval": "error", 75 | "no-ex-assign": "error", 76 | "no-extend-native": "error", 77 | "no-extra-bind": "error", 78 | "no-extra-boolean-cast": "error", 79 | "no-extra-parens": ["error", "functions"], 80 | "no-fallthrough": "error", 81 | "no-floating-decimal": "error", 82 | "no-func-assign": "error", 83 | "no-global-assign": "error", 84 | "no-implied-eval": "error", 85 | "no-inner-declarations": ["error", "functions"], 86 | "no-invalid-regexp": "error", 87 | "no-irregular-whitespace": "error", 88 | "no-iterator": "error", 89 | "no-label-var": "error", 90 | "no-labels": ["error", { "allowLoop": false, "allowSwitch": false }], 91 | "no-lone-blocks": "error", 92 | "no-mixed-operators": ["error", { 93 | "groups": [ 94 | ["==", "!=", "===", "!==", ">", ">=", "<", "<="], 95 | ["&&", "||"], 96 | ["in", "instanceof"] 97 | ], 98 | "allowSamePrecedence": true 99 | }], 100 | "no-mixed-spaces-and-tabs": "error", 101 | "no-multi-spaces": "error", 102 | "no-multi-str": "error", 103 | "no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 0 }], 104 | "no-negated-in-lhs": "error", 105 | "no-new": "error", 106 | "no-new-func": "error", 107 | "no-new-object": "error", 108 | "no-new-require": "error", 109 | "no-new-symbol": "error", 110 | "no-new-wrappers": "error", 111 | "no-obj-calls": "error", 112 | "no-octal": "error", 113 | "no-octal-escape": "error", 114 | "no-path-concat": "error", 115 | "no-proto": "error", 116 | "no-redeclare": "error", 117 | "no-regex-spaces": "error", 118 | "no-return-assign": ["error", "except-parens"], 119 | "no-return-await": "error", 120 | "no-self-assign": "error", 121 | "no-self-compare": "error", 122 | "no-sequences": "error", 123 | "no-shadow-restricted-names": "error", 124 | "no-sparse-arrays": "error", 125 | "no-tabs": "error", 126 | "no-template-curly-in-string": "error", 127 | "no-this-before-super": "error", 128 | "no-throw-literal": "error", 129 | "no-trailing-spaces": "error", 130 | "no-undef": "error", 131 | "no-undef-init": "error", 132 | "no-unexpected-multiline": "error", 133 | "no-unmodified-loop-condition": "error", 134 | "no-unneeded-ternary": ["error", { "defaultAssignment": false }], 135 | "no-unreachable": "error", 136 | "no-unsafe-finally": "error", 137 | "no-unsafe-negation": "error", 138 | "no-unused-expressions": ["error", { "allowShortCircuit": true, "allowTernary": true, "allowTaggedTemplates": true }], 139 | "no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }], 140 | "no-use-before-define": ["error", { "functions": false, "classes": false, "variables": false }], 141 | "no-useless-call": "error", 142 | "no-useless-computed-key": "error", 143 | "no-useless-constructor": "error", 144 | "no-useless-escape": "error", 145 | "no-useless-rename": "error", 146 | "no-useless-return": "error", 147 | "no-whitespace-before-property": "error", 148 | "no-with": "error", 149 | "object-property-newline": ["error", { "allowMultiplePropertiesPerLine": true }], 150 | "one-var": ["error", { "initialized": "never" }], 151 | "operator-linebreak": ["error", "after", { "overrides": { "?": "before", ":": "before" } }], 152 | "padded-blocks": ["error", { "blocks": "never", "switches": "never", "classes": "never" }], 153 | "prefer-promise-reject-errors": "error", 154 | "quotes": ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": true }], 155 | "rest-spread-spacing": ["error", "never"], 156 | "semi": ["error", "never"], 157 | "semi-spacing": ["error", { "before": false, "after": true }], 158 | "space-before-blocks": ["error", "always"], 159 | "space-before-function-paren": ["error", "always"], 160 | "space-in-parens": ["error", "never"], 161 | "space-infix-ops": "error", 162 | "space-unary-ops": ["error", { "words": true, "nonwords": false }], 163 | "spaced-comment": ["error", "always", { 164 | "line": { "markers": ["*package", "!", "/", ",", "="] }, 165 | "block": { "balanced": true, "markers": ["*package", "!", ",", ":", "::", "flow-include"], "exceptions": ["*"] } 166 | }], 167 | "symbol-description": "error", 168 | "template-curly-spacing": ["error", "never"], 169 | "template-tag-spacing": ["error", "never"], 170 | "unicode-bom": ["error", "never"], 171 | "use-isnan": "error", 172 | "valid-typeof": ["error", { "requireStringLiterals": true }], 173 | "wrap-iife": ["error", "any", { "functionPrototypeMethods": true }], 174 | "yield-star-spacing": ["error", "both"], 175 | "yoda": ["error", "never"], 176 | 177 | "import/export": "error", 178 | "import/first": "error", 179 | "import/no-duplicates": "error", 180 | "import/no-webpack-loader-syntax": "error", 181 | 182 | "node/no-deprecated-api": "error", 183 | "node/process-exit-as-throw": "error", 184 | 185 | "promise/param-names": "error", 186 | 187 | "standard/array-bracket-even-spacing": ["error", "either"], 188 | "standard/computed-property-even-spacing": ["error", "even"], 189 | "standard/no-callback-literal": "error", 190 | "standard/object-curly-even-spacing": ["error", "either"] 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Dependency directory 7 | node_modules 8 | 9 | # Compiled 10 | dist 11 | release 12 | .cache 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "10" 4 | - "11" 5 | - "12" 6 | 7 | sudo: false 8 | 9 | install: 10 | - yarn 11 | 12 | script: 13 | - yarn build 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Marcus Asplund 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hyperapp-RxJS", 3 | "version": "0.1.0", 4 | "author": "Marcus Asplund (@marcusasplund)", 5 | "license": "MIT", 6 | "scripts": { 7 | "start": "standard && parcel src/index.html -p 3000 --open", 8 | "build": "rm -rf release && standard && parcel build src/index.html -d build --public-url ./" 9 | }, 10 | "main": "src/index.js", 11 | "repository": { 12 | "type": "git", 13 | "url": "git+ssh://git@github.com/marcusasplund/hyperapp-RxJS.git" 14 | }, 15 | "bugs": { 16 | "url": "https://github.com/marcusasplund/hyperapp-RxJS/issues" 17 | }, 18 | "homepage": "https://github.com/marcusasplund/hyperapp-RxJS#readme", 19 | "cache": { 20 | "inDev": true, 21 | "swDest": "service-worker.js" 22 | }, 23 | "devDependencies": { 24 | "@babel/core": "^7.8.7", 25 | "@babel/preset-env": "7.8.7", 26 | "babel-eslint": "^10.1.0", 27 | "node-sass": "^4.12.0", 28 | "parcel-bundler": "^1.12.3", 29 | "parcel-plugin-sw-cache": "^0.3.1", 30 | "standard": ">=14.3.2" 31 | 32 | }, 33 | "standard": { 34 | "parser": "babel-eslint", 35 | "ignore": [ 36 | "dist/", 37 | "build/" 38 | ] 39 | }, 40 | "dependencies": { 41 | "hyperapp": "1.x.x", 42 | "rxjs": "6.x.x" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Hyperapp with RxJS 2 | 3 | 4 | [![GitHub issues](https://img.shields.io/github/issues/marcusasplund/hyperapp-RxJS.svg)](https://github.com/marcusasplund/hyperapp-RxJS/issues) 5 | [![Build status](https://img.shields.io/travis/marcusasplund/hyperapp-RxJS.svg)](https://travis-ci.org/marcusasplund/hyperapp-RxJS) 6 | [![dependencies](https://img.shields.io/david/marcusasplund/hyperapp-RxJS.svg)](https://david-dm.org/marcusasplund/hyperapp-RxJS) 7 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/2f1636aa184449439ed07ab0f850444b)](https://www.codacy.com/app/marcusasplund/hyperapp-RxJS?utm_source=github.com&utm_medium=referral&utm_content=marcusasplund/hyperapp-RxJS&utm_campaign=Badge_Grade) 8 | 9 | [![Standard - JavaScript Style Guide](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) 10 | 11 | [Hyperapp](https://github.com/hyperapp/hyperapp), test with [RxJS](https://github.com/reactivex/rxjs) 12 | 13 | Offline support with service worker 14 | 15 | From [this excellent article](https://glebbahmutov.com/blog/pure-programming-with-hyper-app/) 16 | 17 | # [demo](https://pap.as/hyperapp/RxJS/) 18 | 19 | 20 | ## installation 21 | 22 | ````bash 23 | $ git clone https://github.com/marcusasplund/hyperapp-RxJS.git 24 | 25 | $ cd hyperapp-RxJS 26 | 27 | $ yarn 28 | 29 | $ yarn start 30 | ```` 31 | 32 | Open up application at http://localhost:4000/ in browser 33 | 34 | ## build a release 35 | 36 | ````bash 37 | $ yarn run build 38 | ```` 39 | This will generate a release directory with your minified/rev'd assets. 40 | 41 | -------------------------------------------------------------------------------- /src/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcusasplund/hyperapp-RxJS/8b6de6a54167bf5d31648e54a47d50701cb82e69/src/android-chrome-192x192.png -------------------------------------------------------------------------------- /src/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcusasplund/hyperapp-RxJS/8b6de6a54167bf5d31648e54a47d50701cb82e69/src/android-chrome-512x512.png -------------------------------------------------------------------------------- /src/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcusasplund/hyperapp-RxJS/8b6de6a54167bf5d31648e54a47d50701cb82e69/src/apple-touch-icon.png -------------------------------------------------------------------------------- /src/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #ffffff 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcusasplund/hyperapp-RxJS/8b6de6a54167bf5d31648e54a47d50701cb82e69/src/favicon-16x16.png -------------------------------------------------------------------------------- /src/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcusasplund/hyperapp-RxJS/8b6de6a54167bf5d31648e54a47d50701cb82e69/src/favicon-32x32.png -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcusasplund/hyperapp-RxJS/8b6de6a54167bf5d31648e54a47d50701cb82e69/src/favicon.ico -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HyperApp RxJS 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 40 |
41 | 42 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import { app } from 'hyperapp' 2 | import { view } from './views/' 3 | import { delayedClicks$ } from './utils/delayed-click' 4 | import './styles/app.scss' 5 | 6 | const state = { 7 | count: 0 8 | } 9 | const actions = { 10 | add: () => state => ({ 11 | count: ++state.count 12 | }), 13 | sub: () => state => ({ 14 | count: --state.count 15 | }), 16 | scheduleAdd: () => (state, actions) => { 17 | delayedClicks$.next(actions.add) 18 | }, 19 | scheduleSub: () => (state, actions) => { 20 | delayedClicks$.next(actions.sub) 21 | } 22 | } 23 | 24 | window.main = app(state, actions, view, document.getElementById('app')) 25 | -------------------------------------------------------------------------------- /src/manifest.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "dir": "ltr", 3 | "lang": "en", 4 | "name": "HyperApp RxJS", 5 | "scope": "./", 6 | "display": "fullscreen", 7 | "start_url": "./", 8 | "short_name": "RxJS", 9 | "theme_color": "white", 10 | "description": "hyperapp test with RxJS", 11 | "orientation": "portrait", 12 | "background_color": "white", 13 | "icons": [{ 14 | "src": "./apple-touch-icon.png", 15 | "sizes": "180x180", 16 | "type": "image/png" 17 | },{ 18 | "src": "./android-chrome-192x192.png", 19 | "sizes": "192x192", 20 | "type": "image/png" 21 | },{ 22 | "src": "./android-chrome-512x512.png", 23 | "sizes": "512x512", 24 | "type": "image/png" 25 | }] 26 | } 27 | -------------------------------------------------------------------------------- /src/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcusasplund/hyperapp-RxJS/8b6de6a54167bf5d31648e54a47d50701cb82e69/src/mstile-150x150.png -------------------------------------------------------------------------------- /src/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/styles/_sakura.scss: -------------------------------------------------------------------------------- 1 | /* Sakura.css v1.0.0 2 | * ================ 3 | * Minimal css theme. 4 | * Project: https://github.com/oxalorg/sakura 5 | */ 6 | 7 | /* Body */ 8 | 9 | html { 10 | font-size: 62.5%; // So that root size becomes 10px 11 | font-family: $font-family-serif; 12 | } 13 | 14 | body { 15 | // $font-size-base must be a rem value 16 | font-size: $font-size-base; 17 | line-height: 1.618; 18 | max-width: 38em; 19 | margin: auto; 20 | color: $color-text; 21 | background-color: $color-bg; 22 | padding: 13px; 23 | } 24 | 25 | @media (max-width: 684px) { 26 | body { 27 | font-size: $font-size-base * 0.85; 28 | } 29 | } 30 | 31 | @media (max-width: 382px) { 32 | body { 33 | font-size: $font-size-base * 0.75; 34 | } 35 | } 36 | 37 | @mixin word-wrap() { 38 | overflow-wrap: break-word; 39 | word-wrap: break-word; 40 | -ms-word-break: break-all; 41 | word-break: break-word; 42 | -ms-hyphens: auto; 43 | -moz-hyphens: auto; 44 | -webkit-hyphens: auto; 45 | hyphens: auto; 46 | } 47 | 48 | h1, h2, h3, h4, h5, h6 { 49 | line-height: 1.1; 50 | font-family: $font-family-sans-serif; 51 | font-weight: 700; 52 | @include word-wrap; 53 | } 54 | 55 | h1 { font-size: 2.35em } 56 | h2 { font-size: 2.00em } 57 | h3 { font-size: 1.75em } 58 | h4 { font-size: 1.5em } 59 | h5 { font-size: 1.25em } 60 | h6 { font-size: 1em } 61 | 62 | small, sub, sup { 63 | font-size: 75%; 64 | } 65 | 66 | hr { 67 | border-color: $color-blossom; 68 | } 69 | 70 | a { 71 | text-decoration: none; 72 | color: $color-blossom; 73 | 74 | &:hover { 75 | color: $color-fade; 76 | border-bottom: 2px solid $color-text; 77 | } 78 | 79 | } 80 | 81 | ul { 82 | padding-left: 1.4em; 83 | } 84 | 85 | li { 86 | margin-bottom: 0.4em; 87 | } 88 | 89 | blockquote { 90 | font-style: italic; 91 | margin-left: 1.5em; 92 | padding-left: 1em; 93 | border-left: 3px solid $color-blossom; 94 | } 95 | 96 | img { 97 | max-width: 100%; 98 | } 99 | 100 | /* Pre and Code */ 101 | 102 | pre { 103 | background-color: $color-bg-alt; 104 | display: block; 105 | padding: 1em; 106 | overflow-x: auto; 107 | } 108 | 109 | code { 110 | font-size: 0.9em; 111 | padding: 0 0.5em; 112 | background-color: $color-bg-alt; 113 | white-space: pre-wrap; 114 | } 115 | 116 | pre > code { 117 | padding: 0; 118 | background-color: transparent; 119 | white-space: pre; 120 | } 121 | 122 | /* Tables */ 123 | 124 | table { 125 | text-align: justify; 126 | width: 100%; 127 | border-collapse: collapse; 128 | } 129 | 130 | td, th { 131 | padding: 0.5em; 132 | border-bottom: 1px solid $color-bg-alt; 133 | } 134 | 135 | /* Buttons, forms and input */ 136 | 137 | input, textarea { 138 | border: 1px solid $color-text; 139 | 140 | &:focus { 141 | border: 1px solid $color-blossom; 142 | } 143 | } 144 | 145 | textarea { 146 | width: 100%; 147 | } 148 | 149 | .button, button, input[type="submit"], input[type="reset"], input[type="button"] { 150 | display: inline-block; 151 | padding: 5px 10px; 152 | text-align: center; 153 | text-decoration: none; 154 | white-space: nowrap; 155 | 156 | background-color: $color-blossom; 157 | color: $color-bg; 158 | border-radius: 1px; 159 | border: 1px solid $color-blossom; 160 | cursor: pointer; 161 | box-sizing: border-box; 162 | 163 | &[disabled] { 164 | cursor: default; 165 | opacity: .5; 166 | } 167 | 168 | &:focus, &:hover { 169 | background-color: $color-fade; 170 | border-color: $color-fade; 171 | color: $color-bg; 172 | outline: 0; 173 | } 174 | } 175 | 176 | textarea, select, input[type] { 177 | color: $color-text; 178 | padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ 179 | margin-bottom: 10px; 180 | background-color: $color-bg-alt; 181 | border: 1px solid $color-bg-alt; 182 | border-radius: 4px; 183 | box-shadow: none; 184 | box-sizing: border-box; 185 | 186 | &:focus { 187 | border: 1px solid $color-blossom; 188 | outline: 0; 189 | } 190 | } 191 | 192 | input[type="checkbox"]:focus { 193 | outline: 1px dotted $color-blossom; 194 | } 195 | 196 | label, legend, fieldset { 197 | display: block; 198 | margin-bottom: .5rem; 199 | font-weight: 600; 200 | } 201 | -------------------------------------------------------------------------------- /src/styles/_show-console.scss: -------------------------------------------------------------------------------- 1 | #console-log-div { 2 | background-color: #272822; 3 | color: #F92672; 4 | padding: 5px 10px; 5 | border-radius: 5px; 6 | font-family: monospace; 7 | margin: 20px 10px 10px; 8 | border: 1px solid black; 9 | max-height: 300px; 10 | overflow-y: auto; 11 | } 12 | 13 | .log { 14 | color: #efefef; 15 | } 16 | 17 | .error { 18 | color: brightpink; 19 | } 20 | 21 | .warn { 22 | color: orange; 23 | } 24 | -------------------------------------------------------------------------------- /src/styles/app.scss: -------------------------------------------------------------------------------- 1 | $color-blossom: #2c8898; 2 | $color-fade: #982c61; 3 | 4 | $color-bg: #f9f9f9; 5 | $color-bg-alt: #f1f1f1; 6 | 7 | $color-text: #4a4a4a; 8 | $font-size-base: 1.8rem; 9 | 10 | $font-family-sans-serif: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif !important; 11 | $font-family-serif: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif !important; 12 | 13 | @import 'show-console'; 14 | @import 'sakura'; 15 | -------------------------------------------------------------------------------- /src/utils/delayed-click.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import { Observable, Subject, of } from 'rxjs' 3 | import { delay, pipe } from 'rxjs/operators' 4 | 5 | const delay$ = delay(600) 6 | 7 | const delayedClicks$ = (new Subject()) 8 | .pipe(delay$) 9 | 10 | const started = window.performance.now() 11 | 12 | delayedClicks$.subscribe(callback => { 13 | const time = window.performance.now() - started 14 | console.log(`executing at ${time.toFixed(2)} ms`) 15 | callback() 16 | }) 17 | 18 | export { delayedClicks$ } 19 | -------------------------------------------------------------------------------- /src/views/add-button.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import { h } from 'hyperapp' 3 | 4 | export const AddButton = ({ actions }) => 5 | 7 | -------------------------------------------------------------------------------- /src/views/header-section.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import { h } from 'hyperapp' 3 | 4 | export const HeaderSection = () => 5 |
6 |

hyperapp RxJS

7 |

8 | 9 | 10 | click away, clicks will be captured and actions will be queued up, then executed with minimum 600ms between each 11 | {' '} 12 | 13 | source 14 | 15 | 16 |

17 |
18 |
19 | -------------------------------------------------------------------------------- /src/views/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import { h } from 'hyperapp' 3 | import { HeaderSection } from './header-section' 4 | import { AddButton } from './add-button' 5 | import { SubButton } from './sub-button' 6 | import { ShowConsole } from './show-console' 7 | 8 | export const view = (state, actions) => 9 |
10 | 11 |

{state.count}

12 | 13 | 14 | 15 |
16 | -------------------------------------------------------------------------------- /src/views/show-console.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import { h } from 'hyperapp' 3 | 4 | const log = console.log 5 | const logError = console.error 6 | const logWarn = console.warn 7 | let index = 0 8 | const logs = [] 9 | 10 | export const ShowConsole = () => 11 |
12 | { 13 | logs.map((logitem, i) => 14 | createLogNode(logitem, i)) 15 | } 16 |
17 | 18 | const pushLogs = (a, type) => { 19 | const args = Array.prototype.slice.call(a) 20 | for (var i = 0; i < args.length; i++) { 21 | logs.unshift({ 22 | message: args[i], 23 | type: type, 24 | index: ++index 25 | }) 26 | } 27 | } 28 | 29 | console.log = function () { 30 | log.apply(console, arguments) 31 | pushLogs(arguments, 'log') 32 | } 33 | 34 | console.error = function () { 35 | logError.apply(console, arguments) 36 | pushLogs(arguments, 'error') 37 | } 38 | 39 | console.warn = function () { 40 | logWarn.apply(console, arguments) 41 | pushLogs(arguments, 'warn') 42 | } 43 | 44 | const createLogNode = (logitem, i) => 45 |
46 | {logitem.index + '. '}{logitem.message} 47 |
48 | -------------------------------------------------------------------------------- /src/views/sub-button.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | import { h } from 'hyperapp' 3 | 4 | export const SubButton = ({ actions }) => 5 | 7 | --------------------------------------------------------------------------------