sygnal 1.0.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -8
- package/dist/extra/classes.js +124 -0
- package/dist/index.js +40 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# Sygnal
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
An intuitive framework for building fast and small components or applications based on Cycle.js
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
## Cycle.js
|
|
7
7
|
|
|
8
8
|
Cycle.js is a functional reactive coding framework that asks 'what if the user was a function?'
|
|
9
9
|
|
|
10
|
-
It is worth reading the summary on the [Cycle.js homepage](https://cycle.js.org/ "Cycle.js Homepage"), but essentially Cycle.js allows you to write simple, concise, extensible, and testable code.
|
|
10
|
+
It is worth reading the summary on the [Cycle.js homepage](https://cycle.js.org/ "Cycle.js Homepage"), but essentially Cycle.js allows you to write simple, concise, extensible, and testable code using a functional reactive style, and helps ensure that all side-effects are isolated away from your component code.
|
|
11
11
|
|
|
12
12
|
## Sygnal
|
|
13
13
|
|
|
@@ -42,7 +42,7 @@ Sygnal's component() function is the only thing needed to create a stand-alone c
|
|
|
42
42
|
The 3 most common/useful parameters to component() are:
|
|
43
43
|
- **model**: an object that maps 'action' names to the commands or reducers that tell Cycle.js drivers **WHAT** to do
|
|
44
44
|
- **intent**: a function that receives Cycle.js sources and returns a map of 'action' names to observable streams telling the application **WHEN** that action should happen.
|
|
45
|
-
- **view**: a function receiving the current application state and returning virtual DOM elements (using either Preact style h() functions
|
|
45
|
+
- **view**: a function receiving the current application state and returning virtual DOM elements (using either Preact style h() functions or by using JSX transpiling using snabbdom-pragma)
|
|
46
46
|
|
|
47
47
|
Essentially the **'model'** parameter determines **WHAT** should happnen, the **'intent'** parameter determines **WHEN** things happen, the **'view'** parameter determines **WHERE** everything is rendered in the browser, and the provided Cycle.js **'drivers'** determine **HOW** things happen.
|
|
48
48
|
|
|
@@ -83,9 +83,9 @@ A very common task in web pages and browser applications is to work with form in
|
|
|
83
83
|
|
|
84
84
|
## Prerequisites
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
For plain Javascript usage, Sygnal has no prerequisites as all dependencies are pre-bundled.
|
|
87
87
|
|
|
88
|
-
To bootstrap a minimal Sygnal application using Vite and JSX:
|
|
88
|
+
To bootstrap a minimal Sygnal application using Vite and that supports JSX:
|
|
89
89
|
|
|
90
90
|
```bash
|
|
91
91
|
npx degit tpresley/sygnal-template my-awesome-app
|
|
@@ -106,7 +106,7 @@ The results will be in the 'dist' folder, and you can serve it locally by runnin
|
|
|
106
106
|
npm preview
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
-
Alternatively, you can use any other bundler of your choice (Webpack, Babel, Rollup, etc.).
|
|
109
|
+
Alternatively, you can use any other bundler of your choice (Webpack, Babel, Rollup, etc.). To use JSX in your components while using alternative bundlers, you will need to install [snabbdom-pragma](https://www.npmjs.com/package/snabbdom-pragma) and configure your bundler to use it for transforming JSX (see [examples here](https://www.npmjs.com/package/snabbdom-pragma#usage "snabbdom-pragma bundler configuration examples")).
|
|
110
110
|
|
|
111
111
|
|
|
112
112
|
## Initialization
|
|
@@ -161,7 +161,7 @@ export default component({
|
|
|
161
161
|
//
|
|
162
162
|
// view: ({ state }) => h('h2', `Hello ${ state.who }`)
|
|
163
163
|
//
|
|
164
|
-
// but you will need to add "import { h } from
|
|
164
|
+
// but you will need to add "import { h } from 'sygnal'" to the top of your file
|
|
165
165
|
})
|
|
166
166
|
```
|
|
167
167
|
|
|
@@ -314,4 +314,7 @@ export default component({
|
|
|
314
314
|
|
|
315
315
|
Sygnal is the result of several years of building Cycle.js apps, and our attempts to make that process more enjoyable. It has been used for moderate scale production applications, and we are making it available to the world in the hopes it is useful, and brings more attention to the wonderful work of the Cycle.js team.
|
|
316
316
|
|
|
317
|
-
|
|
317
|
+
Until better documentation is available, here are some well-commented projects using most of Sygnal's features:
|
|
318
|
+
- Sygnal ToDoMVC ( [GitHub](https://github.com/tpresley/sygnal-todomvc) | [Live Demo](https://tpresley.github.io/sygnal-todomvc/) ) - The [ToDoMVC](https://todomvc.com/) framework comparison app implemented in Sygnal
|
|
319
|
+
- Sygnal 2048 ( [GitHub](https://github.com/tpresley/sygnal-2048) | [Live Demo](https://tpresley.github.io/sygnal-2048/) ) - The [2048 Game](https://github.com/gabrielecirulli/2048 "Original 2048 GitHub repo") implemeted in Sygnal
|
|
320
|
+
- Sygnal Calculator ( [GitHub](https://github.com/tpresley/sygnal-calculator) | [Live Demo](https://tpresley.github.io/sygnal-calculator/) ) - A simple calculator implemeted in Sygnal
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* return a validated and properly separated string of CSS class names from any number of strings, arrays, and objects
|
|
4
|
+
*
|
|
5
|
+
* @param {...String|Array|Object} args any number of strings or arrays with valid CSS class names, or objects where the keys are valid class names and the values evaluate to true or false
|
|
6
|
+
* @return {String} list of `active` classes separated by spaces
|
|
7
|
+
*
|
|
8
|
+
* any `string` or `array` arguments are simply validated and appended to the result
|
|
9
|
+
* `objects` will evaluate the values (which can be booleans or functions), and the keys with `thruthy` values will be validated and appended to the result
|
|
10
|
+
* this function makes it easier to set dynamic classes on HTML elements
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
Object.defineProperty(exports, "__esModule", {
|
|
14
|
+
value: true
|
|
15
|
+
});
|
|
16
|
+
exports["default"] = classes;
|
|
17
|
+
|
|
18
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
19
|
+
|
|
20
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
21
|
+
|
|
22
|
+
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
|
|
23
|
+
|
|
24
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
25
|
+
|
|
26
|
+
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
27
|
+
|
|
28
|
+
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
29
|
+
|
|
30
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
31
|
+
|
|
32
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
33
|
+
|
|
34
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
35
|
+
|
|
36
|
+
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
37
|
+
|
|
38
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
|
39
|
+
|
|
40
|
+
function classes() {
|
|
41
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
42
|
+
args[_key] = arguments[_key];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return args.reduce(function (acc, arg) {
|
|
46
|
+
if (typeof arg === 'string' && !acc.includes(arg)) {
|
|
47
|
+
acc.push.apply(acc, _toConsumableArray(classes_processString(arg)));
|
|
48
|
+
} else if (Array.isArray(arg)) {
|
|
49
|
+
acc.push.apply(acc, _toConsumableArray(classes_processArray(arg)));
|
|
50
|
+
} else if (_typeof(arg) === 'object') {
|
|
51
|
+
acc.push.apply(acc, _toConsumableArray(classes_processObject(arg)));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return acc;
|
|
55
|
+
}, []).join(' ');
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* validate a string as a CSS class name
|
|
59
|
+
*
|
|
60
|
+
* @param {String} className CSS class name to validate
|
|
61
|
+
* @return {Boolean} true if the name is a valid CSS class, false otherwise
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
function isValidClassName(className) {
|
|
66
|
+
return /^[a-zA-Z0-9-_]+$/.test(className);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* find and validate CSS class names in a string
|
|
70
|
+
*
|
|
71
|
+
* @param {String} str string containing one or more CSS class names
|
|
72
|
+
* @return {Array} valid CSS classnames from the provided string
|
|
73
|
+
*/
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
function classes_processString(str) {
|
|
77
|
+
if (typeof str !== 'string') throw new Error('Class name must be a string');
|
|
78
|
+
return str.trim().split(' ').reduce(function (acc, item) {
|
|
79
|
+
if (item.trim().length === 0) return acc;
|
|
80
|
+
if (!isValidClassName(item)) throw new Error("".concat(item, " is not a valid CSS class name"));
|
|
81
|
+
acc.push(item);
|
|
82
|
+
return acc;
|
|
83
|
+
}, []);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* find and validate CSS class names in an array of strings
|
|
87
|
+
*
|
|
88
|
+
* @param {Array} arr array containing one or more strings with valid CSS class names
|
|
89
|
+
* @return {Array} valid CSS class names from the provided array
|
|
90
|
+
*/
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
function classes_processArray(arr) {
|
|
94
|
+
return arr.map(classes_processString).flat();
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* find and validate CSS class names in an object, and exclude keys whose value evaluates to `false`
|
|
98
|
+
*
|
|
99
|
+
* @param {Object} obj object with keys as CSS class names and values which if `truthy` cause the associated key to be returned
|
|
100
|
+
* @return {Array} valid CSS class names from the keys of the provided object where the associated value evaluated to `true`
|
|
101
|
+
*
|
|
102
|
+
* the value for each key can be either a value that evaluates to a boolean or a function that returns a boolean
|
|
103
|
+
* if the value is a function, it will be run and the returned value will be used
|
|
104
|
+
*/
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
function classes_processObject(obj) {
|
|
108
|
+
var ret = Object.entries(obj).filter(function (_ref) {
|
|
109
|
+
var _ref2 = _slicedToArray(_ref, 2),
|
|
110
|
+
key = _ref2[0],
|
|
111
|
+
predicate = _ref2[1];
|
|
112
|
+
|
|
113
|
+
return typeof predicate === 'function' ? predicate() : !!predicate;
|
|
114
|
+
}).map(function (_ref3) {
|
|
115
|
+
var _ref4 = _slicedToArray(_ref3, 2),
|
|
116
|
+
key = _ref4[0],
|
|
117
|
+
_ = _ref4[1];
|
|
118
|
+
|
|
119
|
+
var trimmed = key.trim();
|
|
120
|
+
if (!isValidClassName(trimmed)) throw new Error("".concat(trimmed, " is not a valid CSS class name"));
|
|
121
|
+
return trimmed;
|
|
122
|
+
});
|
|
123
|
+
return ret;
|
|
124
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -5,12 +5,28 @@ function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" =
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", {
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
|
+
var _exportNames = {
|
|
9
|
+
component: true,
|
|
10
|
+
ABORT: true,
|
|
11
|
+
collection: true,
|
|
12
|
+
switchable: true,
|
|
13
|
+
processForm: true,
|
|
14
|
+
run: true,
|
|
15
|
+
classes: true,
|
|
16
|
+
xs: true
|
|
17
|
+
};
|
|
8
18
|
Object.defineProperty(exports, "ABORT", {
|
|
9
19
|
enumerable: true,
|
|
10
20
|
get: function get() {
|
|
11
21
|
return _component.ABORT;
|
|
12
22
|
}
|
|
13
23
|
});
|
|
24
|
+
Object.defineProperty(exports, "classes", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function get() {
|
|
27
|
+
return _classes["default"];
|
|
28
|
+
}
|
|
29
|
+
});
|
|
14
30
|
Object.defineProperty(exports, "collection", {
|
|
15
31
|
enumerable: true,
|
|
16
32
|
get: function get() {
|
|
@@ -41,6 +57,12 @@ Object.defineProperty(exports, "switchable", {
|
|
|
41
57
|
return _switchable["default"];
|
|
42
58
|
}
|
|
43
59
|
});
|
|
60
|
+
Object.defineProperty(exports, "xs", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function get() {
|
|
63
|
+
return _xstream["default"];
|
|
64
|
+
}
|
|
65
|
+
});
|
|
44
66
|
|
|
45
67
|
var _component = _interopRequireWildcard(require("./component"));
|
|
46
68
|
|
|
@@ -52,6 +74,24 @@ var _processForm = _interopRequireDefault(require("./extra/processForm"));
|
|
|
52
74
|
|
|
53
75
|
var _run = _interopRequireDefault(require("./extra/run"));
|
|
54
76
|
|
|
77
|
+
var _classes = _interopRequireDefault(require("./extra/classes"));
|
|
78
|
+
|
|
79
|
+
var _dom = require("@cycle/dom");
|
|
80
|
+
|
|
81
|
+
Object.keys(_dom).forEach(function (key) {
|
|
82
|
+
if (key === "default" || key === "__esModule") return;
|
|
83
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
84
|
+
if (key in exports && exports[key] === _dom[key]) return;
|
|
85
|
+
Object.defineProperty(exports, key, {
|
|
86
|
+
enumerable: true,
|
|
87
|
+
get: function get() {
|
|
88
|
+
return _dom[key];
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
var _xstream = _interopRequireDefault(require("xstream"));
|
|
94
|
+
|
|
55
95
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
56
96
|
|
|
57
97
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
package/package.json
CHANGED