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 CHANGED
@@ -1,13 +1,13 @@
1
1
  # Sygnal
2
2
 
3
- Simple library for making clean Cycle.js components
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 from snabbdom or by using JSX transpiling using snabbdom-pragma)
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
- The only prerequisites to use Sygnal are Cycle.js itself and either @cycle/dom or snabbdom-pragma for virtual dom rendering. However, to handle more advanced observable/stream operations, it's helpful to install [xstream](https://github.com/staltz/xstream "xstream reactive stream library"), an observable library similar to Most or RxJS that is extremely small and fast, and is tailored for use in browser based functional reactive applications.
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.). In order to generate the required virtual DOM in your 'view' function, you will either need to include [@cycle/dom](https://cycle.js.org/api/dom.html#api-h) to get access to virtual DOM helper functions, or 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")).
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 @cycle/dom" to the top of your file
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
- We will continue to add documentation, example code, and live demonstrations over the coming days and weeks!
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sygnal",
3
- "version": "1.0.1",
3
+ "version": "1.1.2",
4
4
  "description": "An intuitive framework for building fast and small components or applications based on Cycle.js",
5
5
  "main": "./dist/index.js",
6
6
  "exports": "./dist/index.js",