lilact 0.2.3 → 0.4.0
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 +1 -1
- package/dist/lilact.development.min.js +1 -1
- package/dist/lilact.development.min.js.map +1 -1
- package/dist/lilact.production.min.js +1 -1
- package/dist/lilact.production.min.js.map +1 -1
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/accessories.ErrorBoundary.html +8 -8
- package/docs/classes/accessories.Suspense.html +7 -7
- package/docs/classes/components.Component.html +10 -10
- package/docs/classes/components.HTMLComponent.html +10 -10
- package/docs/classes/components.RootComponent.html +10 -10
- package/docs/functions/components.createComponent.html +1 -1
- package/docs/functions/components.createRoot.html +1 -1
- package/docs/functions/components.render.html +1 -1
- package/docs/functions/hooks.forwardRef.html +1 -1
- package/docs/functions/hooks.useImperativeHandle.html +1 -1
- package/docs/functions/misc.toBool.html +3 -0
- package/docs/functions/redux.combineReducers.html +12 -0
- package/docs/functions/redux.connect.html +1 -1
- package/docs/functions/timers.animationFramePromise.html +1 -1
- package/docs/functions/timers.clearInterval.html +1 -1
- package/docs/functions/timers.clearTimeout.html +1 -1
- package/docs/functions/timers.grabTimers.html +1 -1
- package/docs/functions/timers.pauseTimers.html +1 -1
- package/docs/functions/timers.releaseTimers.html +1 -1
- package/docs/functions/timers.resetTimers.html +1 -1
- package/docs/functions/timers.resumeTimers.html +1 -1
- package/docs/functions/timers.setInterval.html +1 -1
- package/docs/functions/timers.setTimeout.html +1 -1
- package/docs/functions/timers.timeoutPromise.html +1 -1
- package/docs/index.html +2 -2
- package/docs/modules/misc.html +1 -1
- package/docs/modules/redux.html +1 -1
- package/docs/static/demos/form-elements.jsx +110 -0
- package/docs/static/index.html +2 -1
- package/docs/static/lilact.development.min.js +1 -1
- package/docs/static/lilact.production.min.js +1 -1
- package/package.json +2 -2
- package/root/demos/form-elements.jsx +110 -0
- package/root/index.html +2 -1
- package/root/lilact.development.min.js +1 -1
- package/root/lilact.production.min.js +1 -1
- package/src/components.jsx +27 -10
- package/src/hooks.jsx +1 -2
- package/src/jsx.js +5 -1
- package/src/lilact.jsx +3 -7
- package/src/misc.jsx +42 -14
- package/src/redux.jsx +60 -55
- package/src/timers.jsx +7 -2
- package/webpack.config.js +1 -1
package/src/misc.jsx
CHANGED
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
modification, are permitted provided that the following conditions are met:
|
|
11
11
|
|
|
12
12
|
* Redistributions of source code must retain the above copyright
|
|
13
|
-
|
|
13
|
+
notice, this list of conditions and the following disclaimer.
|
|
14
14
|
* Redistributions in binary form must reproduce the above copyright
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
notice, this list of conditions and the following disclaimer in the
|
|
16
|
+
documentation and/or other materials provided with the distribution.
|
|
17
17
|
|
|
18
18
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
19
19
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
@@ -38,10 +38,10 @@ const typeOf = (input) => {
|
|
|
38
38
|
// used for object comparison functions
|
|
39
39
|
// https://monsterlessons-academy.com/posts/shallow-comparison-vs-deep-comparison-in-javascript
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
const rawObject = Object.prototype.toString.call(input).toLowerCase();
|
|
42
|
+
const typeOfRegex = /\[object (.*)]/g;
|
|
43
|
+
const type = typeOfRegex.exec(rawObject)[1];
|
|
44
|
+
return type;
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
|
|
@@ -347,7 +347,7 @@ export function isClass(func) {
|
|
|
347
347
|
* @returns True if the value is an async function; otherwise false.
|
|
348
348
|
*/
|
|
349
349
|
export function isAsync(fn) {
|
|
350
|
-
|
|
350
|
+
return typeof fn === 'function' && fn.constructor && fn.constructor.name === 'AsyncFunction';
|
|
351
351
|
}
|
|
352
352
|
|
|
353
353
|
/**
|
|
@@ -370,7 +370,25 @@ export function isError(x) {
|
|
|
370
370
|
return x instanceof Error || Object.prototype.toString.call(x) === '[object Error]';
|
|
371
371
|
}
|
|
372
372
|
|
|
373
|
+
/**
|
|
374
|
+
* Converts the input to a boolean value
|
|
375
|
+
*
|
|
376
|
+
* @param value - Value to inspect.
|
|
377
|
+
* @returns boolean value
|
|
378
|
+
*/
|
|
379
|
+
export function toBool(x) {
|
|
380
|
+
if (typeof x === "boolean") return x;
|
|
381
|
+
|
|
382
|
+
if (typeof x === "number") return x !== 0;
|
|
383
|
+
|
|
384
|
+
if (typeof x === "string") {
|
|
385
|
+
x = x.trim().toLowerCase();
|
|
386
|
+
if (x === "true") return true;
|
|
387
|
+
if (x === "false") return false;
|
|
388
|
+
}
|
|
373
389
|
|
|
390
|
+
return Boolean(x);
|
|
391
|
+
}
|
|
374
392
|
|
|
375
393
|
|
|
376
394
|
// Internals
|
|
@@ -395,13 +413,18 @@ export let update_cbs = new Set;
|
|
|
395
413
|
/** @ignore */
|
|
396
414
|
export let roots = new Set;
|
|
397
415
|
/** @ignore */
|
|
398
|
-
export let special_attributes = new Set(["classname", "classname", "ref", "action", "lilact_jsx_loc", "children", "key"]);
|
|
399
|
-
/** @ignore */
|
|
400
416
|
export let err = null; // this is only to ease debuggin,
|
|
401
417
|
/** @ignore */
|
|
402
418
|
export let layout_effects = new Set;
|
|
419
|
+
|
|
403
420
|
/** @ignore */
|
|
404
|
-
export
|
|
421
|
+
export const special_attributes = new Set([
|
|
422
|
+
"classname", "classname", "ref", "action", "lilact_jsx_loc", "children", "key",
|
|
423
|
+
"defaultvalue", "defaultchecked"
|
|
424
|
+
]);
|
|
425
|
+
|
|
426
|
+
/** @ignore */
|
|
427
|
+
export const events_set = new Set([
|
|
405
428
|
"onafterprint","onbeforeprint","onbeforeunload","onerror","onhashchange","onload","onmessage",
|
|
406
429
|
"onoffline","ononline","onpagehide","onpageshow","onpopstate","onresize","onstorage","onunload",
|
|
407
430
|
"onblur","onchange","oncontextmenu","onfocus","oninput","oninvalid","onreset","onsearch","onselect",
|
|
@@ -418,14 +441,19 @@ export let events_set = new Set([
|
|
|
418
441
|
|
|
419
442
|
"onpointerdown", "onpointerup", "onpointermove", "onpointercancel", "onpointerover", "onpointerout",
|
|
420
443
|
"onpointerenter", "onpointerleave"
|
|
421
|
-
])
|
|
444
|
+
]);
|
|
445
|
+
|
|
422
446
|
/** @ignore */
|
|
423
|
-
export
|
|
447
|
+
export const length_css_attributes_set = new Set([
|
|
424
448
|
"width","height","minWidth","minHeight","maxWidth","maxHeight","top","right","bottom","left","margin",
|
|
425
449
|
"marginTop","marginRight","marginBottom","marginLeft","padding","paddingTop","paddingRight","paddingBottom",
|
|
426
450
|
"paddingLeft","borderWidth","borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth",
|
|
427
451
|
"outlineWidth","fontSize","lineHeight","letterSpacing","wordSpacing","textIndent","borderRadius",
|
|
428
452
|
"borderTopLeftRadius","borderTopRightRadius","borderBottomLeftRadius","borderBottomRightRadius",
|
|
429
453
|
"columnGap","rowGap","gap"
|
|
430
|
-
])
|
|
454
|
+
]);
|
|
431
455
|
|
|
456
|
+
/** @ignore */
|
|
457
|
+
export const boolean_html_attributes_set = new
|
|
458
|
+
Set(["disabled", "readOnly", "required", "checked", "multiple",
|
|
459
|
+
"hidden","open","loop","muted","controls","playsInline","allowFullScreen"]);
|
package/src/redux.jsx
CHANGED
|
@@ -81,68 +81,35 @@ export function useDispatch()
|
|
|
81
81
|
* @param [equalityFn=(a, b) => a === b] - Determines when the selected value should update.
|
|
82
82
|
* @returns The selected slice of state.
|
|
83
83
|
*/
|
|
84
|
-
export function useSelector(selector, equalityFn = (a, b) => a === b)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const [, forceRender] = Lilact.useState(0);
|
|
90
|
-
|
|
91
|
-
if (!latestSelectorRef.current) {
|
|
92
|
-
latestSelectorRef.current = selector;
|
|
93
|
-
}
|
|
94
|
-
latestSelectorRef.current = selector;
|
|
95
|
-
|
|
96
|
-
let selected = selector(store.getState()); // todo: should exception be covered?
|
|
84
|
+
export function useSelector(selector, equalityFn = (a, b) => a === b) {
|
|
85
|
+
const store = Lilact.useStore();
|
|
86
|
+
const latestSelected = Lilact.useRef();
|
|
87
|
+
const selectorRef = Lilact.useRef(selector);
|
|
88
|
+
selectorRef.current = selector;
|
|
97
89
|
|
|
98
|
-
|
|
99
|
-
latestSelectedRef.current = selected;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
Lilact.useLayoutEffect(() => {
|
|
103
|
-
// keep latestSelectedRef in sync after render (in case selector used props or similar)
|
|
104
|
-
latestSelectedRef.current = selected;
|
|
105
|
-
}, [selected]);
|
|
90
|
+
const [selected, setSelected] = Lilact.useState(() => selector(store.getState()));
|
|
106
91
|
|
|
107
|
-
|
|
92
|
+
// Keep ref in sync for the subscription callback
|
|
93
|
+
latestSelected.current = selected;
|
|
108
94
|
|
|
109
|
-
|
|
95
|
+
Lilact.useEffect(() => {
|
|
96
|
+
function checkForUpdates() {
|
|
97
|
+
const nextSelected = selectorRef.current(store.getState());
|
|
98
|
+
if (!equalityFn(latestSelected.current, nextSelected)) {
|
|
99
|
+
latestSelected.current = nextSelected;
|
|
100
|
+
setSelected(nextSelected);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
110
103
|
|
|
111
|
-
|
|
112
|
-
if (didUnsubscribe) return;
|
|
113
|
-
try {
|
|
114
|
-
const newSelected = latestSelectorRef.current(store.getState());
|
|
115
|
-
const oldSelected = latestSelectedRef.current;
|
|
116
|
-
if (!equalityFn(oldSelected, newSelected)) {
|
|
117
|
-
latestSelectedRef.current = newSelected;
|
|
104
|
+
const unsubscribe = store.subscribe(checkForUpdates);
|
|
118
105
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
} catch (err) {
|
|
106
|
+
// In case state changed between render and effect
|
|
107
|
+
checkForUpdates();
|
|
122
108
|
|
|
123
|
-
|
|
124
|
-
|
|
109
|
+
return unsubscribe;
|
|
110
|
+
}, [store, equalityFn]);
|
|
125
111
|
|
|
126
|
-
|
|
127
|
-
// (could instead log or ignore)
|
|
128
|
-
// throw err;
|
|
129
|
-
console.warn(err);
|
|
130
|
-
ʔ }
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const unsubscribe = store.subscribe(checkForUpdates);
|
|
135
|
-
|
|
136
|
-
// run check once in case state changed between render and effect
|
|
137
|
-
checkForUpdates();
|
|
138
|
-
|
|
139
|
-
return () => {
|
|
140
|
-
didUnsubscribe = true;
|
|
141
|
-
unsubscribe();
|
|
142
|
-
};
|
|
143
|
-
}, [store, equalityFn]);
|
|
144
|
-
|
|
145
|
-
return latestSelectedRef.current;
|
|
112
|
+
return selected;
|
|
146
113
|
}
|
|
147
114
|
|
|
148
115
|
|
|
@@ -196,3 +163,41 @@ export function connect(mapStateToProps, mapDispatchToProps)
|
|
|
196
163
|
};
|
|
197
164
|
}
|
|
198
165
|
|
|
166
|
+
/**
|
|
167
|
+
* Creates a root reducer by mapping keys to slice reducers.
|
|
168
|
+
*
|
|
169
|
+
* Each slice reducer is called with:
|
|
170
|
+
* - the previous slice state at `state[key]` (or `undefined` initially)
|
|
171
|
+
* - the dispatched action
|
|
172
|
+
*
|
|
173
|
+
* The returned reducer builds the next state object using all reducer keys.
|
|
174
|
+
* If none of the slice reducers produce a change (reference equality),
|
|
175
|
+
* the previous `state` object is returned to avoid unnecessary updates.
|
|
176
|
+
*
|
|
177
|
+
* @param {object} reducers - An object whose values are reducers.
|
|
178
|
+
* @returns {function} A root reducer function compatible with your createStore.
|
|
179
|
+
*/
|
|
180
|
+
export function combineReducers(reducers) {
|
|
181
|
+
const reducerKeys = Object.keys(reducers);
|
|
182
|
+
|
|
183
|
+
for (const key of reducerKeys) {
|
|
184
|
+
if (typeof reducers[key] !== "function") {
|
|
185
|
+
throw new Error(`combineReducers: reducer for key "${key}" is not a function`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return function rootReducer(state = {}, action) {
|
|
190
|
+
let hasChanged = false;
|
|
191
|
+
const nextState = {};
|
|
192
|
+
|
|
193
|
+
for (const key of reducerKeys) {
|
|
194
|
+
const reducer = reducers[key];
|
|
195
|
+
const prevSlice = state[key];
|
|
196
|
+
const nextSlice = reducer(prevSlice, action);
|
|
197
|
+
nextState[key] = nextSlice;
|
|
198
|
+
hasChanged = hasChanged || nextSlice !== prevSlice;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return hasChanged ? nextState : state;
|
|
202
|
+
};
|
|
203
|
+
}
|
package/src/timers.jsx
CHANGED
|
@@ -38,11 +38,16 @@
|
|
|
38
38
|
/**
|
|
39
39
|
* Timer helpers for a promise-friendly timer framework.
|
|
40
40
|
*
|
|
41
|
-
* These functions keep the same call signatures as the standard JavaScript timer APIs where applicable
|
|
41
|
+
* These functions keep the same call signatures as the standard JavaScript timer APIs where applicable
|
|
42
|
+
* (`setTimeout`/`setInterval`/`clearTimeout`/`clearInterval`),
|
|
43
|
+
* but add extra capabilities for promise-friendly control and lifecycle management.
|
|
44
|
+
*
|
|
45
|
+
* This module can “grab” timers and later pause/resume/reset/release them, plus provide promise wrappers
|
|
46
|
+
* like `timeoutPromise` and `animationFramePromise`.
|
|
42
47
|
*
|
|
43
48
|
* - `setTimeout` / `setInterval`: schedule callbacks (same interface as the built-ins).
|
|
44
49
|
* - `clearTimeout` / `clearInterval`: cancel scheduled timers (same interface as the built-ins).
|
|
45
|
-
* - `grabTimers` / `pauseTimers` / `resumeTimers` / `resetTimers` / `releaseTimers`: manage tracked timers
|
|
50
|
+
* - `grabTimers` / `pauseTimers` / `resumeTimers` / `resetTimers` / `releaseTimers`: manage tracked timers.
|
|
46
51
|
* - `timeoutPromise` / `animationFramePromise`: promise-based convenience wrappers.
|
|
47
52
|
*/
|
|
48
53
|
|
package/webpack.config.js
CHANGED
|
@@ -56,7 +56,7 @@ export default (env, argv) => {
|
|
|
56
56
|
optimization: {
|
|
57
57
|
concatenateModules: true, // scope hoisting
|
|
58
58
|
moduleIds: 'deterministic', // smaller stable ids (or 'hashed')
|
|
59
|
-
minimize: true
|
|
59
|
+
minimize: true //mode === 'production',
|
|
60
60
|
},
|
|
61
61
|
experiments: {
|
|
62
62
|
outputModule: true // enable module output
|