solarite 0.3.0 → 0.3.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.
Files changed (34) hide show
  1. package/dist/Solarite-debug.js +411 -524
  2. package/dist/Solarite.js +394 -507
  3. package/dist/Solarite.min.js +2 -2
  4. package/package.json +5 -6
  5. package/readme.md +2 -2
  6. package/src/{solarite/ExprPath.js → ExprPath.js} +43 -58
  7. package/src/{solarite/Globals.js → Globals.js} +4 -4
  8. package/src/{util/MultiValueMap.js → MultiValueMap.js} +1 -32
  9. package/src/{solarite/NodeGroup.js → NodeGroup.js} +30 -26
  10. package/src/{solarite/Shell.js → Shell.js} +8 -7
  11. package/src/Solarite.d.ts +62 -0
  12. package/src/{solarite/Solarite.js → Solarite.js} +13 -15
  13. package/src/{solarite/Template.js → Template.js} +1 -1
  14. package/src/{solarite/Util.js → Util.js} +49 -45
  15. package/src/{solarite/createSolarite.js → createSolarite.js} +12 -10
  16. package/src/{solarite/getArg.js → getArg.js} +24 -3
  17. package/src/{solarite/h.js → h.js} +4 -12
  18. package/src/unused/FastLookupArray.js +54 -0
  19. package/src/unused/Hashes.js +339 -0
  20. package/src/unused/InUse.test.js +92 -0
  21. package/src/unused/InUseMap.js +98 -0
  22. package/src/unused/LinkedList.js +117 -0
  23. package/src/unused/LinkedList.test.js +115 -0
  24. package/src/unused/Misc.js +13 -0
  25. package/src/unused/Perf.js +47 -0
  26. package/src/unused/TrackedArray.js +54 -0
  27. package/src/unused/WeakArray.js +33 -0
  28. package/src/{solarite/watch.js → watch.js} +4 -4
  29. package/src/util/Util.js +0 -101
  30. /package/src/{solarite/HtmlParser.js → HtmlParser.js} +0 -0
  31. /package/src/{util/Errors.js → assert.js} +0 -0
  32. /package/src/{util/delve.js → delve.js} +0 -0
  33. /package/src/{solarite/hash.js → hash.js} +0 -0
  34. /package/src/{solarite/udomdiff.js → udomdiff.js} +0 -0
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Solarite JavasCript UI library.
3
+ * MIT License
4
+ * https://vorticode.github.io/solarite/
5
+ */
6
+
7
+ export default function h(htmlStrings?: HTMLElement | string | string[] | Function | {render: Function}, ...exprs: any[]): Node | HTMLElement | Template | Function;
8
+ export { default as h, default as r } from './h.js';
9
+
10
+ export const ArgType: {
11
+ Bool: string;
12
+ Int: string;
13
+ Float: string;
14
+ String: string;
15
+ Json: string;
16
+ Eval: string;
17
+ }
18
+
19
+ export function getArg(el:HTMLElement, attributeName:string, defaultValue?:any,
20
+ type?:typeof ArgType[keyof typeof ArgType] | Function | any[], fallback?:any): any;
21
+
22
+ export interface RenderOptions {
23
+ styles?: boolean;
24
+ scripts?: boolean;
25
+ ids?: boolean;
26
+ render?: boolean;
27
+ }
28
+
29
+ export class Template {
30
+ exprs: (Template|string|Function)[];
31
+ html: string[];
32
+ constructor(htmlStrings: string[], exprs: any[]);
33
+ render(el?: HTMLElement, options?: RenderOptions): DocumentFragment | HTMLElement | null;
34
+ getExactKey(): string;
35
+ getCloseKey(): string;
36
+ }
37
+
38
+ export function delve(obj: object, path: string[], createVal?: any): any;
39
+
40
+
41
+
42
+ // Experimental:
43
+ //--------------
44
+
45
+ // Globals object
46
+ export const Globals: {
47
+ componentArgsHash: WeakMap<any, any>;
48
+ connected: WeakSet<HTMLElement>;
49
+ currentExprPath: any;
50
+ div: HTMLDivElement;
51
+ elementClasses: {[key: string]: typeof Node};
52
+ htmlProps: {[key: string]: boolean};
53
+ nodeEvents: WeakMap<Node, {[eventName: string]: [Function, Function, any[]]}>;
54
+ nodeGroups: WeakMap<HTMLElement, any>;
55
+ objToEl: WeakMap<any, any>;
56
+ rendered: WeakSet<HTMLElement>;
57
+ rendering: WeakSet<HTMLElement>;
58
+ shells: WeakMap<string[], any>;
59
+ reset: Function;
60
+ count: number;
61
+ };
62
+
@@ -3,36 +3,34 @@
3
3
  * MIT License
4
4
  * https://vorticode.github.io/solarite/
5
5
  */
6
- /** @jsx r */
7
- /** @jsxFrag null */
8
6
 
7
+ import h from './h.js';
8
+ export default h;
9
+ export {default as h, default as r} from './h.js'; //Named exports for h() are deprecated.
10
+ export {default as delve} from './delve.js';
11
+ export {getArg, ArgType} from './getArg.js';
12
+ export {default as Template} from './Template.js';
13
+
14
+
15
+
16
+ // Experimental:
17
+ //--------------
18
+ export {setArgs} from './getArg.js';
9
19
 
10
20
  import createSolarite from "./createSolarite.js";
11
21
 
12
22
  /**
13
23
  * TODO: The Proxy and the multiple base classes mess up 'instanceof Solarite'
14
24
  * @type {Node|Class<HTMLElement>|function(tagName:string):Node|Class<HTMLElement>} */
15
- let Solarite = new Proxy(createSolarite(), {
25
+ const Solarite = new Proxy(createSolarite(), {
16
26
  apply(self, _, args) {
17
27
  return createSolarite(...args)
18
28
  }
19
29
  });
20
30
 
21
- import h from './h.js';
22
- export default h;
23
-
24
31
  /** @type {HTMLElement|Class} */
25
32
  export {Solarite}
26
- export {default as h, default as r} from './h.js';
27
- export {getArg, ArgType} from './getArg.js';
28
- export {default as Template} from './Template.js';
29
33
  export {default as Globals} from './Globals.js';
30
-
31
- import Util from './Util.js';
32
- let getInputValue = Util.getInputValue;
33
- export {getInputValue};
34
- export {default as delve} from '../util/delve.js';
35
34
  export {default as SolariteUtil} from './Util.js';
36
35
 
37
- //Experimental:
38
36
  //export {default as watch, renderWatched} from './watch.js'; // unfinished
@@ -1,4 +1,4 @@
1
- import {assert} from "../util/Errors.js";
1
+ import {assert} from "./assert.js";
2
2
  import {getObjectHash, getObjectId} from "./hash.js";
3
3
  import Globals from "./Globals.js";
4
4
  import {RootNodeGroup} from "./NodeGroup.js";
@@ -1,8 +1,23 @@
1
1
  import Globals from "./Globals.js";
2
- import delve from "../util/delve.js";
2
+ import delve from "./delve.js";
3
3
 
4
4
  let Util = {
5
5
 
6
+ /**
7
+ * Returns true if they're the same.
8
+ * @param a
9
+ * @param b
10
+ * @returns {boolean} */
11
+ arraySame(a, b) {
12
+ let aLength = a.length;
13
+ if (aLength !== b.length)
14
+ return false;
15
+ for (let i=0; i<aLength; i++)
16
+ if (a[i] !== b[i])
17
+ return false;
18
+ return true; // the same.
19
+ },
20
+
6
21
  bindId(root, el) {
7
22
  let id = el.getAttribute('data-id') || el.getAttribute('id');
8
23
  if (id) { // If something hasn't removed the id.
@@ -43,7 +58,6 @@ let Util = {
43
58
  }
44
59
  },
45
60
 
46
-
47
61
  /**
48
62
  * Convert a Proper Case name to a name with dashes.
49
63
  * Dashes will be placed between letters and numbers.
@@ -111,17 +125,17 @@ let Util = {
111
125
  * for (const item of flatten(complexArray))
112
126
  * console.log(item); // Outputs: 1, 2, 3, 4, 5, 6, { a: 'object' }, 7, 8, 9
113
127
  */
114
- *flatten(value) {
115
- if (Array.isArray(value)) {
116
- for (const item of value) {
117
- yield* Util.flatten(item); // Recursively flatten arrays
118
- }
119
- } else if (typeof value === 'function') {
120
- const result = value();
121
- yield* Util.flatten(result); // Recursively flatten the result of a function
122
- } else
123
- yield value; // Yield primitive values as is
124
- },
128
+ // *flatten(value) {
129
+ // if (Array.isArray(value)) {
130
+ // for (const item of value) {
131
+ // yield* Util.flatten(item); // Recursively flatten arrays
132
+ // }
133
+ // } else if (typeof value === 'function') {
134
+ // const result = value();
135
+ // yield* Util.flatten(result); // Recursively flatten the result of a function
136
+ // } else
137
+ // yield value; // Yield primitive values as is
138
+ // },
125
139
 
126
140
  /**
127
141
  * Get the value of an input as the most appropriate JavaScript type.
@@ -143,6 +157,10 @@ let Util = {
143
157
  return node.value; // String
144
158
  },
145
159
 
160
+ isEvent(attrName) {
161
+ return attrName.startsWith('on') && attrName in Globals.div;
162
+ },
163
+
146
164
  /**
147
165
  * @param el {HTMLElement}
148
166
  * @param prop {string}
@@ -182,9 +200,10 @@ let Util = {
182
200
  return val === undefined || val === false || val === null;
183
201
  },
184
202
 
203
+ /*
185
204
  isPrimitive(val) {
186
205
  return typeof val === 'string' || typeof val === 'number'
187
- },
206
+ },*/
188
207
 
189
208
  /**
190
209
  * If val is a function, evaluate it recursively until the result is not a function.
@@ -202,6 +221,22 @@ let Util = {
202
221
  return val;
203
222
  },
204
223
 
224
+ /**
225
+ * Use an array as the value of a map, appending to it when we add.
226
+ * Used by watch.js.
227
+ * @param map {Map|WeakMap|Object}
228
+ * @param key
229
+ * @param value */
230
+ mapArrayAdd(map, key, value) {
231
+ let result = map.get(key);
232
+ if (!result) {
233
+ result = [value];
234
+ map.set(key, result);
235
+ }
236
+ else
237
+ result.push(value);
238
+ },
239
+
205
240
  /**
206
241
  * Remove nodes from the beginning and end that are not:
207
242
  * 1. Elements.
@@ -232,37 +267,6 @@ export default Util;
232
267
 
233
268
 
234
269
 
235
- let isEvent = attrName => attrName.startsWith('on') && attrName in Globals.div;
236
- export {isEvent};
237
-
238
-
239
- export function dashesToCamel(str) {
240
- return str.replace(/-([a-z])/g, g => g[1].toUpperCase());
241
- }
242
-
243
-
244
-
245
-
246
-
247
- /**
248
- * Returns true if they're the same.
249
- * @param a
250
- * @param b
251
- * @returns {boolean} */
252
- export function arraySame(a, b) {
253
- let aLength = a.length;
254
- if (aLength !== b.length)
255
- return false;
256
- for (let i=0; i<aLength; i++)
257
- if (a[i] !== b[i])
258
- return false;
259
- return true; // the same.
260
- }
261
-
262
-
263
-
264
-
265
-
266
270
  // For debugging only
267
271
  //#IFDEV
268
272
  export function setIndent(items, level=1) {
@@ -1,10 +1,9 @@
1
- import Util from "../util/Util.js";
2
- import SolariteUtil from './Util.js';
1
+ import Util from './Util.js';
3
2
  import Globals from "./Globals.js";
4
3
 
5
4
  function defineClass(Class, tagName, extendsTag) {
6
5
  if (!customElements[getName](Class)) { // If not previously defined.
7
- tagName = tagName || SolariteUtil.camelToDashes(Class.name)
6
+ tagName = tagName || Util.camelToDashes(Class.name)
8
7
  if (!tagName.includes('-'))
9
8
  tagName += '-element';
10
9
 
@@ -70,10 +69,10 @@ export default function createSolarite(extendsTag=null) {
70
69
  * TODO: Make these standalone functions.
71
70
  * Callbacks.
72
71
  * Use onConnect.push(() => ...); to add new callbacks. */
73
- onConnect = Util.callback();
72
+ onConnect;
74
73
 
75
- onFirstConnect = Util.callback();
76
- onDisconnect = Util.callback();
74
+ onFirstConnect;
75
+ onDisconnect;
77
76
 
78
77
  /**
79
78
  * @param options {RenderOptions} */
@@ -89,7 +88,7 @@ export default function createSolarite(extendsTag=null) {
89
88
 
90
89
  // Add slot children before constructor code executes.
91
90
  // This breaks the styleStaticNested test.
92
- // PendingChildren is setup in NodeGroup.createNewComponent()
91
+ // PendingChildren is setup in NodeGroup.instantiateComponent()
93
92
  // TODO: Match named slots.
94
93
  //let ch = Globals.pendingChildren.pop();
95
94
  //if (ch) // TODO: how could there be a slot before render is called?
@@ -131,13 +130,16 @@ export default function createSolarite(extendsTag=null) {
131
130
  this.renderFirstTime();
132
131
  if (!Globals.connected.has(this)) {
133
132
  Globals.connected.add(this);
134
- this.onFirstConnect();
133
+ if (this.onFirstConnect)
134
+ this.onFirstConnect();
135
135
  }
136
- this.onConnect();
136
+ if (this.onConnect)
137
+ this.onConnect();
137
138
  }
138
139
 
139
140
  disconnectedCallback() {
140
- this.onDisconnect();
141
+ if (this.onDisconnect)
142
+ this.onDisconnect();
141
143
  }
142
144
 
143
145
 
@@ -26,7 +26,7 @@ import Util from "./Util.js";
26
26
  * @param el {HTMLElement}
27
27
  * @param attributeName {string} Attribute name. Not case-sensitive.
28
28
  * @param defaultValue {*} Default value to use if attribute doesn't exist.
29
- * @param type {ArgType|function|*[]}
29
+ * @param type {ArgType|function|Class|*[]}
30
30
  * If an array, use the value if it's in the array, otherwise return undefined.
31
31
  * If it's a function, pass the value to the function and return the result.
32
32
  * @param fallback {*} If the defaultValue is undefiend and type can't be parsed as the given type, use this value.
@@ -41,8 +41,11 @@ export function getArg(el, attributeName, defaultValue=undefined, type=ArgType.S
41
41
  if (Array.isArray(type))
42
42
  return type.includes(val) ? val : fallback;
43
43
 
44
- if (typeof type === 'function')
45
- return type(val);
44
+ if (typeof type === 'function') {
45
+ return type.constructor
46
+ ? new type(val) // arg type is custom Class
47
+ : type(val); // arg type is custom function
48
+ }
46
49
 
47
50
  // If bool, it's true as long as it exists and its value isn't falsey.
48
51
  if (type===ArgType.Bool) {
@@ -84,6 +87,24 @@ export function getArg(el, attributeName, defaultValue=undefined, type=ArgType.S
84
87
  }
85
88
  }
86
89
 
90
+
91
+ /**
92
+ * Experimental. Set multiple arguments/attributes all at once.
93
+ * @param el {HTMLElement}
94
+ * @param args {Record<string, any>}
95
+ * @param types {Record<string, ArgType|function|Class>}
96
+ *
97
+ * @example
98
+ * constructor({user, path}={}) {
99
+ * setArgs(this, arguments[0], {user: User, path: ArgType.String});
100
+ * }
101
+ */
102
+ export function setArgs(el, args, types) {
103
+ for (let name in args)
104
+ this[name] = getArg(el, name, args[name], types[name] || ArgType.String);
105
+ }
106
+
107
+
87
108
  /**
88
109
  * @enum */
89
110
  var ArgType = {
@@ -1,7 +1,7 @@
1
1
  import Template from "./Template.js";
2
2
  import Util from "./Util.js";
3
3
  import Globals from "./Globals.js";
4
- import {assert} from "../util/Errors.js";
4
+ import {assert} from "./assert.js";
5
5
 
6
6
  /**
7
7
  * Convert strings to HTMLNodes.
@@ -35,6 +35,8 @@ import {assert} from "../util/Errors.js";
35
35
  * @return {Node|HTMLElement|Template} */
36
36
  export default function h(htmlStrings=undefined, ...exprs) {
37
37
 
38
+ if (htmlStrings === undefined && !exprs.length && arguments.length)
39
+ throw new Error('h() cannot be called with undefined.');
38
40
 
39
41
  // TODO: Make this a more flat if/else and call other functions for the logic.
40
42
  if (htmlStrings instanceof Node) {
@@ -57,7 +59,7 @@ export default function h(htmlStrings=undefined, ...exprs) {
57
59
  }
58
60
 
59
61
  // 2. Render template created by #4 to element.
60
- else if (exprs[0] instanceof Template) {
62
+ else { // instanceof Template
61
63
  let options = exprs[1];
62
64
  template.render(parent, options);
63
65
 
@@ -68,16 +70,6 @@ export default function h(htmlStrings=undefined, ...exprs) {
68
70
  parent.append(this.rootNg.getParentNode());
69
71
  }
70
72
  }
71
-
72
-
73
-
74
- // null for expr[0], remove whole element.
75
- // This path never happens?
76
- else {
77
- throw new Error('unsupported');
78
- //let ngm = NodeGroupManager.get(parent);
79
- //ngm.render(null, exprs[1])
80
- }
81
73
  }
82
74
 
83
75
  // 3. Path if used as a template tag.
@@ -0,0 +1,54 @@
1
+ /**
2
+ * partialUpdate test is 20% slower when using this, even before I override any methods!*/
3
+ export default class FastLookupArray extends Array {
4
+ constructor() {
5
+ super(...arguments)
6
+ this.indexMap = new Map(); // You can replace with WeakMap() but ensure only objects are added.
7
+
8
+ }
9
+
10
+ push(item) { // doesn't support pushing multiple
11
+ if (!this.indexMap.has(item)) {
12
+ this[this.length] = item;
13
+ this.indexMap.set(item, this.length - 1);
14
+ }
15
+ }
16
+
17
+ indexOf(item) {
18
+ return this.indexMap.get(item) || -1;
19
+ }
20
+
21
+ remove(item) {
22
+ const index = this.indexOf(item);
23
+ if (index !== -1) {
24
+ this.splice(index, 1);
25
+ this.indexMap.delete(item);
26
+
27
+ // Adjust the map indices for the items after the removed one
28
+ for (let i = index; i < this.length; i++)
29
+ this.indexMap.set(this[i], i);
30
+ }
31
+ }
32
+
33
+ insertBefore(referenceItem, newItem) {
34
+ const refIndex = this.indexOf(referenceItem);
35
+ if (refIndex !== -1) {
36
+ this.splice(refIndex, 0, newItem);
37
+ this.indexMap.set(newItem, refIndex);
38
+
39
+ // Adjust the map indices for the items after the inserted one
40
+ for (let i = refIndex + 1; i < this.length; i++)
41
+ this.indexMap.set(this[i], i);
42
+ }
43
+ }
44
+
45
+ set(index, item) {
46
+ const currentItem = this[index];
47
+ if (currentItem !== undefined)
48
+ this.indexMap.delete(currentItem);
49
+ this[index] = item;
50
+ this.indexMap.set(item, index);
51
+ }
52
+
53
+ // TODO: Override splice?
54
+ }