diff options
| author | bozo.kopic <bozo.kopic@gmail.com> | 2020-04-11 02:42:27 +0200 |
|---|---|---|
| committer | bozo.kopic <bozo.kopic@gmail.com> | 2020-04-11 02:42:27 +0200 |
| commit | 816d4add6f017775bc1f6607e392bfb71e393ffa (patch) | |
| tree | 33a25a5b7420c9a1d4d606b312748a5a7426a0b8 /src_js | |
| parent | f8ab65b277c2eb7b9ed0e6d78f0302d388e0eff0 (diff) | |
repository refactoring
Diffstat (limited to 'src_js')
| -rw-r--r-- | src_js/opcut/common.js | 5 | ||||
| -rw-r--r-- | src_js/opcut/ev.js | 22 | ||||
| -rw-r--r-- | src_js/opcut/fs.js | 5 | ||||
| -rw-r--r-- | src_js/opcut/future.js | 47 | ||||
| -rw-r--r-- | src_js/opcut/grid.js | 13 | ||||
| -rw-r--r-- | src_js/opcut/main.js | 12 | ||||
| -rw-r--r-- | src_js/opcut/renderer.js | 180 | ||||
| -rw-r--r-- | src_js/opcut/util.js | 507 | ||||
| -rw-r--r-- | src_js/opcut/validators.js | 2 | ||||
| -rw-r--r-- | src_js/opcut/vt.js | 5 |
10 files changed, 21 insertions, 777 deletions
diff --git a/src_js/opcut/common.js b/src_js/opcut/common.js index 1a8562c..00c7950 100644 --- a/src_js/opcut/common.js +++ b/src_js/opcut/common.js @@ -1,8 +1,9 @@ import * as URI from 'uri-js'; import iziToast from 'izitoast'; -import r from 'opcut/renderer'; -import * as u from 'opcut/util'; +import r from '@hat-core/renderer'; +import * as u from '@hat-core/util'; + import * as states from 'opcut/states'; import * as fs from 'opcut/fs'; diff --git a/src_js/opcut/ev.js b/src_js/opcut/ev.js deleted file mode 100644 index f619998..0000000 --- a/src_js/opcut/ev.js +++ /dev/null @@ -1,22 +0,0 @@ -/** @module opcut/ev */ - -import bean from 'bean'; - -import * as u from 'opcut/util'; - - -export function on(element, eventType, selector, handler, args) { - bean.on(element, eventType, selector, handler, args); -} - -export function one(element, eventType, selector, handler, args) { - bean.one(element, eventType, selector, handler, args); -} - -export function off(element, eventType, handler) { - bean.off(element, eventType, handler); -} - -export function fire(element, eventType, args) { - u.delay(bean.fire, 0, element, eventType, args); -} diff --git a/src_js/opcut/fs.js b/src_js/opcut/fs.js index e748181..6b3c579 100644 --- a/src_js/opcut/fs.js +++ b/src_js/opcut/fs.js @@ -1,8 +1,7 @@ import h from 'hyperscript'; import FileSaver from 'file-saver'; -import * as u from 'opcut/util'; -import * as ev from 'opcut/ev'; +import * as u from '@hat-core/util'; export function loadText(ext) { @@ -11,7 +10,7 @@ export function loadText(ext) { type: 'file', accept: ext}); const promise = new Promise(resolve => { - ev.on(el, 'change', evt => { + el.addEventListener('change', evt => { const file = u.get(['files', 0], evt.target); if (!file) return; diff --git a/src_js/opcut/future.js b/src_js/opcut/future.js deleted file mode 100644 index 22d4b1f..0000000 --- a/src_js/opcut/future.js +++ /dev/null @@ -1,47 +0,0 @@ -/** @module opcut/future */ - - -export function create() { - let data = { - done: false, - error: false, - result: undefined, - resolve: null, - reject: null - }; - let future = new Promise((resolve, reject) => { - data.resolve = resolve; - data.reject = reject; - if (data.error) { - reject(data.result); - } else if (data.done) { - resolve(data.resolve); - } - }); - future.done = () => data.done; - future.result = () => { - if (!data.done) - throw 'Future is not done'; - if (data.error) - throw data.error; - return data.result; - }; - future.setResult = result => { - if (data.done) - throw 'Result already set'; - data.result = result; - data.done = true; - if (data.resolve) - data.resolve(data.result); - }; - future.setError = error => { - if (data.done) - throw 'Result already set'; - data.error = true; - data.result = error; - data.done = true; - if (data.reject) - data.reject(error); - }; - return future; -} diff --git a/src_js/opcut/grid.js b/src_js/opcut/grid.js index 27f9a23..e882093 100644 --- a/src_js/opcut/grid.js +++ b/src_js/opcut/grid.js @@ -1,8 +1,8 @@ import Papa from 'papaparse'; -import r from 'opcut/renderer'; -import * as u from 'opcut/util'; -import * as ev from 'opcut/ev'; +import r from '@hat-core/renderer'; +import * as u from '@hat-core/util'; + import * as fs from 'opcut/fs'; @@ -69,11 +69,10 @@ export function tbody(gridPath, columns, validators) { click: evt => { if (u.equals(gridState.selectedItem, [rowIndex, column])) return; - ev.one(r, 'render', () => { - if (evt.target.firstChild && evt.target.firstChild.focus) - evt.target.firstChild.focus(); - }); r.set([gridPath, 'selectedItem'], [rowIndex, column]); + r.render(); + if (evt.target.firstChild && evt.target.firstChild.focus) + evt.target.firstChild.focus(); } }}, content]; diff --git a/src_js/opcut/main.js b/src_js/opcut/main.js index a6ea938..3cf91b0 100644 --- a/src_js/opcut/main.js +++ b/src_js/opcut/main.js @@ -1,18 +1,18 @@ -import r from 'opcut/renderer'; -import * as u from 'opcut/util'; -import * as ev from 'opcut/ev'; +import * as u from '@hat-core/util'; +import r from '@hat-core/renderer'; + import * as states from 'opcut/states'; import * as vt from 'opcut/vt'; -import 'style/main.scss'; +import 'main.scss'; function main() { - let root = document.body.appendChild(document.createElement('div')); + const root = document.body.appendChild(document.createElement('div')); r.init(root, states.main, vt.main); } -ev.on(window, 'load', main); +window.addEventListener('load', main); window.r = r; window.u = u; diff --git a/src_js/opcut/renderer.js b/src_js/opcut/renderer.js deleted file mode 100644 index 378b3c0..0000000 --- a/src_js/opcut/renderer.js +++ /dev/null @@ -1,180 +0,0 @@ -/** @module opcut/renderer2 */ - -import * as snabbdom from 'snabbdom/es/snabbdom'; -import snabbdomAttributes from 'snabbdom/es/modules/attributes'; -import snabbdomClass from 'snabbdom/es/modules/class'; -import snabbdomProps from 'snabbdom/es/modules/props'; -// import snabbdomStyle from 'snabbdom/es/modules/style'; -import snabbdomDataset from 'snabbdom/es/modules/dataset'; -import snabbdomEvent from 'snabbdom/es/modules/eventlisteners'; - -import * as u from 'opcut/util'; -import * as ev from 'opcut/ev'; - - -const patch = snabbdom.init([ - snabbdomAttributes, - snabbdomClass, - snabbdomProps, - // snabbdomStyle, - snabbdomDataset, - snabbdomEvent -]); - - -function vhFromArray(node) { - if (!node) - return []; - if (u.isString(node)) - return node; - if (!u.isArray(node)) - throw 'Invalid node structure'; - if (node.length < 1) - return []; - if (typeof node[0] != 'string') - return node.map(vhFromArray); - const hasData = node.length > 1 && u.isObject(node[1]); - const children = u.pipe( - u.map(vhFromArray), - u.flatten, - Array.from - )(node.slice(hasData ? 2 : 1)); - const result = hasData ? - snabbdom.h(node[0], node[1], children) : - snabbdom.h(node[0], children); - return result; -} - -/** - * Virtual DOM renderer - */ -export class Renderer { - - /** - * Calls `init` method - * @param {HTMLElement} [el=document.body] - * @param {Any} [initState=null] - * @param {Function} [vtCb=null] - * @param {Number} [maxFps=30] - */ - constructor(el, initState, vtCb, maxFps) { - this.init(el, initState, vtCb, maxFps); - } - - /** - * Initialize renderer - * @param {HTMLElement} [el=document.body] - * @param {Any} [initState=null] - * @param {Function} [vtCb=null] - * @param {Number} [maxFps=30] - * @return {Promise} - */ - init(el, initState, vtCb, maxFps) { - this._state = null; - this._changes = []; - this._promise = null; - this._timeout = null; - this._lastRender = null; - this._vtCb = vtCb; - this._maxFps = u.isNumber(maxFps) ? maxFps : 30; - this._vNode = el || document.querySelector('body'); - if (initState) - return this.change(_ => initState); - return new Promise(resolve => { resolve(); }); - } - - /** - * Get current state value referenced by `paths` - * @param {...Path} paths - * @return {Any} - */ - get(...paths) { - return u.get(paths, this._state); - } - - /** - * Change current state value referenced by `path` - * @param {Path} path - * @param {Any} value - * @return {Promise} - */ - set(path, value) { - if (arguments.length < 2) { - value = path; - path = []; - } - return this.change(path, _ => value); - } - - /** - * Change current state value referenced by `path` - * @param {Path} path - * @param {Function} cb - * @return {Promise} - */ - change(path, cb) { - if (arguments.length < 2) { - cb = path; - path = []; - } - this._changes.push([path, cb]); - if (this._promise) - return this._promise; - this._promise = new Promise((resolve, reject) => { - setTimeout(() => { - try { - this._change(); - } catch(e) { - this._promise = null; - reject(e); - throw e; - } - this._promise = null; - resolve(); - }, 0); - }); - return this._promise; - } - - _change() { - let change = false; - while (this._changes.length > 0) { - const [path, cb] = this._changes.shift(); - const view = u.get(path); - const oldState = this._state; - this._state = u.change(path, cb, this._state); - if (this._state && u.equals(view(oldState), - view(this._state))) - continue; - change = true; - if (!this._vtCb || this._timeout) - continue; - const delay = (!this._lastRender || !this._maxFps ? - 0 : - (1000 / this._maxFps) - - (performance.now() - this._lastRender)); - this._timeout = setTimeout(() => { - this._timeout = null; - this._lastRender = performance.now(); - const vNode = vhFromArray(this._vtCb(this)); - patch(this._vNode, vNode); - this._vNode = vNode; - ev.fire(this, 'render', [this._state]); - }, (delay > 0 ? delay : 0)); - } - if (change) - ev.fire(this, 'change', [this._state]); - } - -} -// Renderer.prototype.set = u.curry(Renderer.prototype.set); -// Renderer.prototype.change = u.curry(Renderer.prototype.change); - - -/** - * Default renderer - * @static - * @type {Renderer} - */ -const defaultRenderer = new Renderer(); -export default defaultRenderer; diff --git a/src_js/opcut/util.js b/src_js/opcut/util.js deleted file mode 100644 index a7aa166..0000000 --- a/src_js/opcut/util.js +++ /dev/null @@ -1,507 +0,0 @@ -/** @module opcut/util */ - -/** - * Identity function - * @function - * @param {Any} obj input object - * @return {Any} same object as input - */ -export const identity = obj => obj; - -/** - * Check if value is Array (wrapper for Array.isArray) - * @function - * @param {Any} arr input object - * @return {Boolean} - */ -export const isArray = Array.isArray; - -/** - * Check if value is Object (not `true` from Array or `null`) - * @function - * @param {Any} obj input object - * @return {Boolean} - */ -export const isObject = obj => obj !== null && - typeof(obj) == 'object' && - !isArray(obj); - -/** - * Check if value is number - * @function - * @param {Any} n input object - * @return {Boolean} - */ -export const isNumber = n => typeof(n) == 'number'; - -/** - * Check if value is integer - * @function - * @param {Any} n input object - * @type {Boolean} - */ -export const isInteger = Number.isInteger; - -/** - * Check if value is string - * @function - * @param {Any} str input object - * @type {Boolean} - */ -export const isString = str => typeof(str) == 'string'; - -/** - * Strictly parse integer from string - * @param {String} value - * @return {Number} - */ -export function strictParseInt(value) { - if (/^(-|\+)?([0-9]+)$/.test(value)) - return Number(value); - return NaN; -} - -/** - * Strictly parse float from string - * @param {String} value - * @return {Number} - */ -export function strictParseFloat(value) { - if (/^(-|\+)?([0-9]+(\.[0-9]+)?)$/.test(value)) - return Number(value); - return NaN; -} - -/** - * Create new deep copy of input value - * @param {Any} value - * @return {Any} copy of value - */ -export function clone(obj) { - if (isArray(obj)) - return Array.from(obj, clone); - if (isObject(obj)) { - let ret = {}; - for (let i in obj) - ret[i] = clone(obj[i]); - return ret; - } - return obj; -} - -/** - * Combine two arrays in single array of pairs - * @param {Array<Any>} arr1 - * @param {Array<Any>} arr2 - * @return {Array<Array<Any>>} - */ -export function zip(arr1, arr2) { - return Array.from((function*() { - for (let i = 0; i < arr1.length || i < arr2.length; ++i) - yield [arr1[i], arr2[i]]; - })()); -} - -/** - * Convert object to array of key, value pairs - * @param {Object} obj - * @return {Array<Array>} - */ -export function toPairs(obj) { - return Object.entries(obj); -} - -/** - * Convert array of key, value pairs to object - * @param {Array<Array>} arr - * @return {Object} - */ -export function fromPairs(arr) { - let ret = {}; - for (let [k, v] of arr) - ret[k] = v; - return ret; -} - -/** - * Flatten nested arrays - * @param {Array} arr - * @return {Generator} - */ -export function* flatten(arr) { - if (isArray(arr)) { - for (let i of arr) - if (isArray(i)) - yield* flatten(i); - else - yield i; - } else { - yield arr; - } -} - -/** - * Pipe function calls (functional composition with reversed order) - * @param {...Function} fns functions - * @return {Function} - */ -export function pipe(...fns) { - if (fns.length < 1) - throw 'no functions'; - return function (...args) { - let ret = fns[0].apply(this, args); - for (let fn of fns.slice(1)) - ret = fn(ret); - return ret; - }; -} - -/** - * Curry function with fixed arguments lenth - * @param {Function} fn - * @return {Function} - */ -export function curry(fn) { - let wrapper = function(oldArgs) { - return function(...args) { - args = oldArgs.concat(args); - if (args.length >= fn.length) - return fn(...args); - return wrapper(args); - }; - }; - return wrapper([]); -} - -/** - * Deep object equality - * (curried function) - * @function - * @param {Any} x - * @param {Any} y - * @return {Boolean} - */ -export const equals = curry((x, y) => { - if (x === y) - return true; - if (typeof(x) != 'object' || - typeof(y) != 'object' || - x === null || - y === null) - return false; - if (Array.isArray(x) || Array.isArray(y)) { - if (!Array.isArray(x) || !Array.isArray(y) || x.length != y.length) - return false; - } - for (let i in x) - if (!equals(x[i], y[i])) - return false; - for (let i in y) - if (!equals(x[i], y[i])) - return false; - return true; -}); - -/** - * Get value from `obj` referenced by `path` - * (curried function) - * @function - * @param {Path} path - * @param {Any} obj - * @return {Any} - */ -export const get = curry((path, obj) => { - let ret = obj; - for (let i of flatten(path)) { - if (ret === null || typeof(ret) != 'object') - return undefined; - ret = ret[i]; - } - return ret; -}); - -/** - * Change `obj` by appling function `fn` to value referenced by `path` - * (curried function) - * @function - * @param {Path} path - * @param {Function} fn - * @param {Any} obj - * @return {Any} changed `obj` - */ -export const change = curry((path, fn, obj) => { - function _change(path, obj) { - if (isInteger(path[0])) { - obj = (isArray(obj) ? Array.from(obj) : []); - } else if (isString(path[0])) { - obj = (isObject(obj) ? Object.assign({}, obj) : {}); - } else { - throw 'invalid path'; - } - if (path.length > 1) { - obj[path[0]] = _change(path.slice(1), obj[path[0]]); - } else { - obj[path[0]] = fn(obj[path[0]]); - } - return obj; - } - path = Array.from(flatten(path)); - if (path.length < 1) - return fn(obj); - return _change(path, obj); -}); - -/** - * Change `obj` by setting value referenced by `path` to `val` - * (curried function) - * @function - * @param {Path} path - * @param {Any} val - * @param {Any} obj - * @return {Any} changed `obj` - */ -export const set = curry((path, val, obj) => change(path, _ => val, obj)); - -/** - * Change `obj` by omitting value referenced by `path` - * (curried function) - * @function - * @param {Path} path - * @param {Any} obj - * @return {Any} changed `obj` - */ -export const omit = curry((path, obj) => { - function _omit(path, obj) { - if (isInteger(path[0])) { - obj = (isArray(obj) ? Array.from(obj) : []); - } else if (isString(path[0])) { - obj = (isObject(obj) ? Object.assign({}, obj) : {}); - } else { - throw 'invalid path'; - } - if (path.length > 1) { - obj[path[0]] = _omit(path.slice(1), obj[path[0]]); - } else if (isInteger(path[0])) { - obj.splice(path[0], 1); - } else { - delete obj[path[0]]; - } - return obj; - } - path = Array.from(flatten(path)); - if (path.length < 1) - return undefined; - return _omit(path, obj); -}); - -/** - * Sort `arr` by with comparison function `fn` - * (curried function) - * @function - * @param {Function} fn - * @param {Array} arr - * @return {Array} sorted `arr` - */ -export const sortBy = curry((fn, arr) => Array.from(arr).sort((x, y) => { - let xVal = fn(x); - let yVal = fn(y); - if (xVal < yVal) - return -1; - if (xVal > yVal) - return 1; - return 0; -})); - -/** - * Create object which is subset `obj` containing only properties defined by - * `arr` - * (curried function) - * @function - * @param {Array} arr - * @param {Object} obj - * @return {Object} subset of `obj` - */ -export const pick = curry((arr, obj) => { - const ret = {}; - for (let i of arr) - if (i in obj) - ret[i] = obj[i]; - return ret; -}); - -/** - * Change `arr` by appling function `fn` to it's elements - * (curried function) - * @function - * @param {Function} fn - * @param {Array} arr - * @return {Array} modified `arr` - */ -export const map = curry((fn, arr) => isArray(arr) ? - arr.map(fn) : - pipe(toPairs, - x => x.map(([k, v]) => [k, fn(v)]), - fromPairs)(arr)); - -/** - * Change `arr` to contain only elements for which function `fn` returns `true` - * (curried function) - * @function - * @param {Function} fn - * @param {Array} arr - * @return {Array} filtered `arr` - */ -export const filter = curry((fn, arr) => arr.filter(fn)); - -/** - * Append `val` to end of `arr` - * (curried function) - * @function - * @param {Any} val - * @param {Array} arr - * @return {Array} `arr` with appended `val` - */ -export const append = curry((val, arr) => arr.concat([val])); - -/** - * Reduce `arr` values by appling function `fn` - * (curried function) - * @function - * @param {Function} fn - * @param {Any} val initial accumulator value - * @param {Array} arr - * @return {Any} reduced value - */ -export const reduce = curry((fn, val, arr) => arr.reduce(fn, val)); - -/** - * Merge two objects - * (curried function) - * @function - * @param {Object} obj1 - * @param {Object} obj2 - * @return {Object} combined `obj1` and `obj2` - */ -export const merge = curry((obj1, obj2) => Object.assign({}, obj1, obj2)); - -/** - * Merge multiple objects - * (curried function) - * @function - * @param {...Object} objs - * @return {Object} combined `objs` - */ -export const mergeAll = reduce(merge, {}); - -/** - * Find element in `arr` for which function `fn` returns `true` - * (curried function) - * @function - * @param {Function} fn - * @param {Array} arr - * @return {Any} - */ -export const find = curry((fn, arr) => arr.find(fn)); - -/** - * Concatenate two arrays - * (curried function) - * @function - * @param {Array} arr1 - * @param {Array} arr2 - * @return {Array} concatenated `arr1` and `arr2` - */ -export const concat = curry((arr1, arr2) => arr1.concat(arr2)); - -/** - * Create union of two arrays using `equals` to check equality - * (curried function) - * @function - * @param {Array} arr1 - * @param {Array} arr2 - * @return {Array} union of `arr1` and `arr2` - */ -export const union = curry((arr1, arr2) => { - return reduce((acc, val) => { - if (!find(equals(val), arr1)) - acc = append(val, acc); - return acc; - }, arr1, arr2); -}); - -/** - * Check if `arr` contains `val` - * (curried function) - * @function - * @param {Any} val - * @param {Array} arr - * @return {Boolean} - */ -export const contains = curry((val, arr) => arr.includes(val)); - -/** - * Insert `val` into `arr` on index `idx` - * (curried function) - * @function - * @param {Number} idx - * @param {Any} val - * @param {Array} arr - * @return {Array} - */ -// TODO: Array.from(arr).splice(idx, 0, val) not working? -export const insert = curry((idx, val, arr) => - arr.slice(0, idx).concat([val], arr.slice(idx))); - -/** - * Reverse array - * @param {Array} arr - * @return {Array} - */ -export function reverse(arr) { - return Array.from(arr).reverse(); -} - -/** - * Array length - * @param {Array} arr - * @return {Number} - */ -export function length(arr) { - return arr.length; -} - -/** - * Create promise that resolves in `t` milliseconds - * @param {Number} t - * @return {Promise} - */ -export function sleep(t) { - return new Promise(resolve => { - setTimeout(() => { resolve(); }, t); - }); -} - - -export const slice = curry((begin, end, arr) => arr.slice(begin, end)); - -export function inc(x) { - return x + 1; -} - -export function dec(x) { - return x - 1; -} - - -/** - * Delay function call `fn(...args)` for `t` milliseconds - * @param {Function} fn - * @param {Number} [t=0] - * @param {...Any} args - * @return {Promise} - */ -export function delay(fn, t, ...args) { - return new Promise(resolve => { - setTimeout(() => { resolve(fn(...args)); }, t || 0); - }); -} diff --git a/src_js/opcut/validators.js b/src_js/opcut/validators.js index 1d2ad32..e5a18c4 100644 --- a/src_js/opcut/validators.js +++ b/src_js/opcut/validators.js @@ -1,4 +1,4 @@ -import * as u from 'opcut/util'; +import * as u from '@hat-core/util'; export function notEmptyValidator(value) { diff --git a/src_js/opcut/vt.js b/src_js/opcut/vt.js index bbfd792..d2f3b7b 100644 --- a/src_js/opcut/vt.js +++ b/src_js/opcut/vt.js @@ -1,5 +1,6 @@ -import r from 'opcut/renderer'; -import * as u from 'opcut/util'; +import r from '@hat-core/renderer'; +import * as u from '@hat-core/util'; + import * as grid from 'opcut/grid'; import * as common from 'opcut/common'; import * as states from 'opcut/states'; |
