lilact 0.9.1 → 0.10.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/dist/lilact.development.js +277 -127
- package/dist/lilact.development.js.map +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/functions/errors.globalErrorHandler.html +3 -2
- package/docs/functions/errors.traceError.html +4 -3
- package/docs/functions/hooks.useImperativeHandle.html +1 -1
- package/docs/functions/misc.classNames.html +1 -1
- package/docs/functions/misc.deepEqual.html +1 -1
- package/docs/functions/misc.forwardRef.html +4 -0
- package/docs/functions/misc.getComponentByPointer.html +1 -1
- package/docs/functions/misc.isAsync.html +1 -1
- package/docs/functions/misc.isClass.html +1 -1
- package/docs/functions/misc.isEmpty.html +1 -1
- package/docs/functions/misc.isError.html +1 -1
- package/docs/functions/misc.isThenable.html +1 -1
- package/docs/functions/misc.shallowEqual.html +1 -1
- package/docs/functions/misc.toBool.html +1 -1
- package/docs/functions/run.lazy.html +1 -1
- package/docs/functions/run.require.html +2 -2
- package/docs/functions/timers.timeoutPromise.html +2 -2
- package/docs/modules/hooks.html +1 -1
- package/docs/modules/misc.html +1 -1
- package/docs/static/demos/reducer.jsx +29 -23
- package/docs/static/lilact.development.js +277 -127
- package/docs/static/lilact.development.min.js +1 -1
- package/docs/static/lilact.production.min.js +1 -1
- package/package.json +1 -1
- package/root/demos/reducer.jsx +29 -23
- package/root/lilact.development.js +277 -127
- package/root/lilact.development.min.js +1 -1
- package/root/lilact.production.min.js +1 -1
- package/src/errors.jsx +36 -32
- package/src/events.jsx +194 -66
- package/src/hooks.jsx +0 -15
- package/src/lilact.jsx +21 -2
- package/src/misc.jsx +14 -0
- package/src/pane.jsx +2 -2
- package/src/run.jsx +4 -4
- package/src/timers.jsx +4 -4
- package/docs/functions/hooks.forwardRef.html +0 -4
package/src/errors.jsx
CHANGED
|
@@ -58,6 +58,7 @@ function getErrorLocation(err) // works for both error and error-event, and also
|
|
|
58
58
|
// Chrome/Edge: at fn (eval:xxx:LINE:COL)
|
|
59
59
|
// Firefox: fn@eval:xxx:LINE:COL
|
|
60
60
|
// Safari: @eval:xxx:LINE:COL (sometimes)
|
|
61
|
+
/** @ignore */
|
|
61
62
|
function parseEvalLocationFromStack(stack, urlPrefix = "eval:/") {
|
|
62
63
|
const raw = typeof stack === "string" ? stack : String(stack || "");
|
|
63
64
|
const lines = raw.split(/\r?\n/);
|
|
@@ -125,34 +126,36 @@ export function scanBlockLabels(code, path)
|
|
|
125
126
|
* Debug tool to get the Lilact traced location of an error. It can also produce some block based stack trace
|
|
126
127
|
* if `Lilact.transpilerConfig.enableLabelStack` is set to `true` before loading the script. This is `false`
|
|
127
128
|
* by default for efficiency.
|
|
129
|
+
*
|
|
130
|
+
* @param error - The error object
|
|
128
131
|
*
|
|
129
132
|
* @returns A new object that includes `path`, `row`, `col`, `msg`, `name`, and optional `stack`.
|
|
130
133
|
* The exception itself is stored as `err`.
|
|
131
134
|
*/
|
|
132
|
-
export function traceError(
|
|
135
|
+
export function traceError(error)
|
|
133
136
|
{
|
|
134
|
-
if(
|
|
135
|
-
return
|
|
137
|
+
if(error?.is_traced) {
|
|
138
|
+
return error;
|
|
136
139
|
}
|
|
137
140
|
|
|
138
|
-
const loc = parseEvalLocationFromStack(
|
|
141
|
+
const loc = parseEvalLocationFromStack(error.stack);
|
|
139
142
|
|
|
140
143
|
const obj = {
|
|
141
|
-
fileName: loc.url?.slice(6) ||
|
|
144
|
+
fileName: loc.url?.slice(6) || error.fileName,
|
|
142
145
|
|
|
143
146
|
lineNumber: loc.line,
|
|
144
147
|
columnNumber: loc.col,
|
|
145
148
|
|
|
146
|
-
message:
|
|
147
|
-
name:
|
|
149
|
+
message: error.message,
|
|
150
|
+
name: error.name,
|
|
148
151
|
|
|
149
|
-
stack:
|
|
150
|
-
_error:
|
|
152
|
+
stack: error.stack,
|
|
153
|
+
_error: error,
|
|
151
154
|
|
|
152
155
|
is_traced: true
|
|
153
156
|
};
|
|
154
157
|
|
|
155
|
-
if(
|
|
158
|
+
if( error.name!=='JSXParseError' ) {
|
|
156
159
|
|
|
157
160
|
let mps;
|
|
158
161
|
|
|
@@ -165,18 +168,18 @@ export function traceError(err)
|
|
|
165
168
|
obj.lineNumber = mloc.line;
|
|
166
169
|
obj.columnNumber = mloc.col;
|
|
167
170
|
}
|
|
168
|
-
else if(
|
|
171
|
+
else if( error.lilact_trace!==undefined) {
|
|
169
172
|
|
|
170
|
-
let loc = getErrorLocation(
|
|
173
|
+
let loc = getErrorLocation(error);
|
|
171
174
|
|
|
172
175
|
let mps;
|
|
173
176
|
let blk;
|
|
174
177
|
|
|
175
|
-
if(typeof(
|
|
176
|
-
blk = Lilact.blocks_info.labels[
|
|
178
|
+
if(typeof(error.lilact_trace)==='object') {
|
|
179
|
+
blk = Lilact.blocks_info.labels[error.lilact_trace[0]];
|
|
177
180
|
}
|
|
178
181
|
else {
|
|
179
|
-
blk = Lilact.blocks_info.labels[
|
|
182
|
+
blk = Lilact.blocks_info.labels[error.lilact_trace];
|
|
180
183
|
}
|
|
181
184
|
|
|
182
185
|
if(blk) {
|
|
@@ -194,8 +197,8 @@ export function traceError(err)
|
|
|
194
197
|
|
|
195
198
|
}
|
|
196
199
|
else {
|
|
197
|
-
const loc = getErrorLocation(
|
|
198
|
-
if(
|
|
200
|
+
const loc = getErrorLocation(error);
|
|
201
|
+
if(error.fileName) obj.fileName = error.fileName;
|
|
199
202
|
obj.lineNumber = loc.line;
|
|
200
203
|
obj.columnNumber = loc.col;
|
|
201
204
|
}
|
|
@@ -219,14 +222,15 @@ export function traceError(err)
|
|
|
219
222
|
* Lilact.globalErrorHandler(e);
|
|
220
223
|
* });
|
|
221
224
|
* `
|
|
225
|
+
* @param error - The error object
|
|
222
226
|
*
|
|
223
227
|
*/
|
|
224
|
-
export function globalErrorHandler(
|
|
228
|
+
export function globalErrorHandler(error)
|
|
225
229
|
{
|
|
226
230
|
Lilact.pauseTimers();
|
|
227
|
-
if(
|
|
231
|
+
if(error.error) error = error.error;
|
|
228
232
|
|
|
229
|
-
|
|
233
|
+
error = Lilact.traceError(error);
|
|
230
234
|
|
|
231
235
|
const cls = Lilact.emotion.css(`
|
|
232
236
|
background: linear-gradient(135deg, #fff2f2d4, #ffffffd4);
|
|
@@ -254,11 +258,11 @@ export function globalErrorHandler(err)
|
|
|
254
258
|
//<b>⚠</b>
|
|
255
259
|
el.innerHTML =
|
|
256
260
|
`<h3 style=""><red>Error!</red></h3>
|
|
257
|
-
<b>${
|
|
258
|
-
${Number.isFinite(
|
|
259
|
-
<b>${
|
|
260
|
-
${Lilact.required_scripts[
|
|
261
|
-
${
|
|
261
|
+
<b>${error.fileName?'At '+error.fileName:''}
|
|
262
|
+
${Number.isFinite(error.lineNumber)?": Line "+(error.lineNumber+1):""}</b><br><br>
|
|
263
|
+
<b>${error.name}</b>: <span>${error.message}</span><br><br>
|
|
264
|
+
${Lilact.required_scripts[error.fileName]?'<code><pre></pre><pre><red></red></pre><pre></pre></code>':''}
|
|
265
|
+
${error._error.componentStackLog?'<br>Component Stack:<br><code><pre>'+error._error.componentStackLog+'</pre></code>':''}
|
|
262
266
|
`;
|
|
263
267
|
|
|
264
268
|
|
|
@@ -266,16 +270,16 @@ export function globalErrorHandler(err)
|
|
|
266
270
|
|
|
267
271
|
const pres = el.querySelectorAll('pre');
|
|
268
272
|
|
|
269
|
-
if(Lilact.required_scripts[
|
|
270
|
-
const lines = Lilact.required_scripts[
|
|
273
|
+
if(Lilact.required_scripts[error.fileName]) {
|
|
274
|
+
const lines = Lilact.required_scripts[error.fileName].code.split("\n");
|
|
271
275
|
|
|
272
|
-
if(lines?.[
|
|
273
|
-
pres[0].innerText = lines[
|
|
276
|
+
if(lines?.[error.lineNumber-1])
|
|
277
|
+
pres[0].innerText = lines[error.lineNumber-1];
|
|
274
278
|
|
|
275
|
-
if(lines?.[
|
|
279
|
+
if(lines?.[error.lineNumber]) el.querySelector('pre red').innerText = lines[error.lineNumber];
|
|
276
280
|
|
|
277
|
-
if(lines?.[
|
|
278
|
-
pres[2].innerText = lines[
|
|
281
|
+
if(lines?.[error.lineNumber+1])
|
|
282
|
+
pres[2].innerText = lines[error.lineNumber+1];
|
|
279
283
|
}
|
|
280
284
|
|
|
281
285
|
el.showModal();
|
package/src/events.jsx
CHANGED
|
@@ -57,79 +57,207 @@ if (typeof Event !== 'undefined' && !Event.prototype.composedPath) {
|
|
|
57
57
|
// Event pool for reuse
|
|
58
58
|
const _pool = [];
|
|
59
59
|
const MAX_POOL_SIZE = 10;
|
|
60
|
+
const POINTER_TYPES = ["mouse", "pen", "touch"];
|
|
60
61
|
|
|
61
62
|
export function createSyntheticEvent(nativeEvent, currentTarget) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
63
|
+
const e = _pool.length ? _pool.pop() : {};
|
|
64
|
+
|
|
65
|
+
e.nativeEvent = nativeEvent;
|
|
66
|
+
e.type = nativeEvent.type;
|
|
67
|
+
e.target = nativeEvent.target || nativeEvent.srcElement || null;
|
|
68
|
+
e.currentTarget = currentTarget || nativeEvent.currentTarget || null;
|
|
69
|
+
e.timeStamp = nativeEvent.timeStamp || Date.now();
|
|
70
|
+
|
|
71
|
+
// Standard flags
|
|
72
|
+
e.defaultPrevented = !!nativeEvent.defaultPrevented;
|
|
73
|
+
e.isPropagationStopped = false;
|
|
74
|
+
e.isPersistent = false;
|
|
75
|
+
|
|
76
|
+
// Common DOM meta when present
|
|
77
|
+
e.bubbles = !!nativeEvent.bubbles;
|
|
78
|
+
e.cancelable = !!nativeEvent.cancelable;
|
|
79
|
+
e.composed = !!nativeEvent.composed;
|
|
80
|
+
e.detail = nativeEvent.detail;
|
|
81
|
+
|
|
82
|
+
e.relatedTarget =
|
|
83
|
+
nativeEvent.relatedTarget ||
|
|
84
|
+
(nativeEvent.fromElement ? nativeEvent.fromElement : null) ||
|
|
85
|
+
(nativeEvent.toElement ? nativeEvent.toElement : null) ||
|
|
86
|
+
null;
|
|
87
|
+
|
|
88
|
+
// Modifier keys
|
|
89
|
+
e.altKey = !!nativeEvent.altKey;
|
|
90
|
+
e.ctrlKey = !!nativeEvent.ctrlKey;
|
|
91
|
+
e.metaKey = !!nativeEvent.metaKey;
|
|
92
|
+
e.shiftKey = !!nativeEvent.shiftKey;
|
|
93
|
+
|
|
94
|
+
// preventDefault / stopPropagation
|
|
95
|
+
e.isDefaultPrevented = () => e.defaultPrevented;
|
|
96
|
+
e.preventDefault = () => {
|
|
97
|
+
if (nativeEvent.preventDefault) nativeEvent.preventDefault();
|
|
98
|
+
e.defaultPrevented = true;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
e.stopPropagation = () => {
|
|
102
|
+
if (nativeEvent.stopPropagation) nativeEvent.stopPropagation();
|
|
103
|
+
e.isPropagationStopped = true;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
e.persist = () => { e.isPersistent = true; };
|
|
107
|
+
|
|
108
|
+
// Key/mouse/pointer related
|
|
109
|
+
e.key = nativeEvent.key || null;
|
|
110
|
+
e.code = nativeEvent.code || null;
|
|
111
|
+
e.which = nativeEvent.which ?? nativeEvent.keyCode ?? null;
|
|
112
|
+
|
|
113
|
+
// Mouse / Pointer button state normalization
|
|
114
|
+
// - "button" often is 0/1/2 for mouse; for pointer events it's also present.
|
|
115
|
+
// - "buttons" is a bitmask of which buttons are down (often important for drag).
|
|
116
|
+
e.button = nativeEvent.button ?? null;
|
|
117
|
+
e.buttons = nativeEvent.buttons ?? null;
|
|
118
|
+
|
|
119
|
+
// Pointer identity + type (critical for multi-touch / pointer capture)
|
|
120
|
+
e.pointerId = nativeEvent.pointerId ?? null;
|
|
121
|
+
e.pointerType = nativeEvent.pointerType ?? null;
|
|
122
|
+
e.isPrimary = nativeEvent.isPrimary ?? null;
|
|
123
|
+
|
|
124
|
+
// Coordinates: React/SyntheticEvent uses these directly (React provides them too)
|
|
125
|
+
e.clientX = nativeEvent.clientX ?? 0;
|
|
126
|
+
e.clientY = nativeEvent.clientY ?? 0;
|
|
127
|
+
e.screenX = nativeEvent.screenX ?? 0;
|
|
128
|
+
e.screenY = nativeEvent.screenY ?? 0;
|
|
129
|
+
|
|
130
|
+
// pageX/pageY might be derived; keep if present
|
|
131
|
+
// (Using pageX/pageY only if you need it; most drag uses clientX/Y.)
|
|
132
|
+
e.pageX = nativeEvent.pageX ?? null;
|
|
133
|
+
e.pageY = nativeEvent.pageY ?? null;
|
|
134
|
+
|
|
135
|
+
// movementX/movementY exist on some mouse events; harmless if absent
|
|
136
|
+
e.movementX = nativeEvent.movementX ?? 0;
|
|
137
|
+
e.movementY = nativeEvent.movementY ?? 0;
|
|
138
|
+
|
|
139
|
+
// Pressure/tilt (Pointer Events)
|
|
140
|
+
e.pressure = nativeEvent.pressure ?? null;
|
|
141
|
+
e.tiltX = nativeEvent.tiltX ?? null;
|
|
142
|
+
e.tiltY = nativeEvent.tiltY ?? null;
|
|
143
|
+
e.width = nativeEvent.width ?? null;
|
|
144
|
+
e.height = nativeEvent.height ?? null;
|
|
145
|
+
|
|
146
|
+
// If the native event has a pointer capture API, you can forward bind/capture calls.
|
|
147
|
+
// (These are methods on the EventTarget, not on the event, but keeping fields is enough.)
|
|
148
|
+
e.pointerEventsSupported = POINTER_TYPES.includes(e.pointerType);
|
|
149
|
+
|
|
150
|
+
// For input-like events normalize value and checked
|
|
151
|
+
try {
|
|
152
|
+
const tgt = e.target;
|
|
153
|
+
e.value = tgt && ("value" in tgt) ? tgt.value : undefined;
|
|
154
|
+
e.checked = tgt && ("checked" in tgt) ? tgt.checked : undefined;
|
|
155
|
+
|
|
156
|
+
// Some input events have selectionStart/selectionEnd etc.
|
|
157
|
+
e.selectionStart = tgt && ("selectionStart" in tgt) ? tgt.selectionStart : undefined;
|
|
158
|
+
e.selectionEnd = tgt && ("selectionEnd" in tgt) ? tgt.selectionEnd : undefined;
|
|
159
|
+
} catch (err) {
|
|
160
|
+
e.value = undefined;
|
|
161
|
+
e.checked = undefined;
|
|
162
|
+
e.selectionStart = undefined;
|
|
163
|
+
e.selectionEnd = undefined;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Touch lists (useful for touch events; sometimes pointerType === "touch" uses pointer events instead)
|
|
167
|
+
// Keep references only if they exist.
|
|
168
|
+
e.touches = nativeEvent.touches || null;
|
|
169
|
+
e.targetTouches = nativeEvent.targetTouches || null;
|
|
170
|
+
e.changedTouches = nativeEvent.changedTouches || null;
|
|
171
|
+
|
|
172
|
+
// composedPath helper
|
|
173
|
+
e.path = typeof nativeEvent.composedPath === "function"
|
|
174
|
+
? nativeEvent.composedPath()
|
|
175
|
+
: [e.target];
|
|
176
|
+
|
|
177
|
+
// Additional keyboard extras when present
|
|
178
|
+
e.repeat = nativeEvent.repeat ?? false;
|
|
179
|
+
e.location = nativeEvent.location ?? 0;
|
|
180
|
+
|
|
181
|
+
return e;
|
|
105
182
|
}
|
|
106
183
|
|
|
107
184
|
export function releaseSyntheticEvent(e) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
185
|
+
if (e && !e.isPersistent) {
|
|
186
|
+
e.nativeEvent = null;
|
|
187
|
+
e.type = null;
|
|
188
|
+
e.target = null;
|
|
189
|
+
e.currentTarget = null;
|
|
190
|
+
e.timeStamp = 0;
|
|
191
|
+
|
|
192
|
+
e.defaultPrevented = false;
|
|
193
|
+
e.isPropagationStopped = false;
|
|
194
|
+
|
|
195
|
+
e.isPersistent = false;
|
|
196
|
+
|
|
197
|
+
e.isDefaultPrevented = null;
|
|
198
|
+
e.preventDefault = null;
|
|
199
|
+
e.stopPropagation = null;
|
|
200
|
+
e.persist = null;
|
|
201
|
+
|
|
202
|
+
e.bubbles = false;
|
|
203
|
+
e.cancelable = false;
|
|
204
|
+
e.composed = false;
|
|
205
|
+
e.detail = undefined;
|
|
206
|
+
e.relatedTarget = null;
|
|
207
|
+
|
|
208
|
+
// modifier keys
|
|
209
|
+
e.altKey = false;
|
|
210
|
+
e.ctrlKey = false;
|
|
211
|
+
e.metaKey = false;
|
|
212
|
+
e.shiftKey = false;
|
|
213
|
+
|
|
214
|
+
// pointer/mouse fields
|
|
215
|
+
e.key = null;
|
|
216
|
+
e.code = null;
|
|
217
|
+
e.which = null;
|
|
218
|
+
|
|
219
|
+
e.button = null;
|
|
220
|
+
e.buttons = null;
|
|
221
|
+
e.pointerId = null;
|
|
222
|
+
e.pointerType = null;
|
|
223
|
+
e.isPrimary = null;
|
|
224
|
+
|
|
225
|
+
e.clientX = 0;
|
|
226
|
+
e.clientY = 0;
|
|
227
|
+
e.screenX = 0;
|
|
228
|
+
e.screenY = 0;
|
|
229
|
+
e.pageX = null;
|
|
230
|
+
e.pageY = null;
|
|
231
|
+
|
|
232
|
+
e.movementX = 0;
|
|
233
|
+
e.movementY = 0;
|
|
234
|
+
|
|
235
|
+
e.pressure = null;
|
|
236
|
+
e.tiltX = null;
|
|
237
|
+
e.tiltY = null;
|
|
238
|
+
e.width = null;
|
|
239
|
+
e.height = null;
|
|
240
|
+
|
|
241
|
+
// input-like
|
|
242
|
+
e.value = undefined;
|
|
243
|
+
e.checked = undefined;
|
|
244
|
+
e.selectionStart = undefined;
|
|
245
|
+
e.selectionEnd = undefined;
|
|
246
|
+
|
|
247
|
+
// touch lists
|
|
248
|
+
e.touches = null;
|
|
249
|
+
e.targetTouches = null;
|
|
250
|
+
e.changedTouches = null;
|
|
251
|
+
|
|
252
|
+
e.path = null;
|
|
253
|
+
e.repeat = false;
|
|
254
|
+
e.location = 0;
|
|
255
|
+
|
|
256
|
+
if (_pool.length < MAX_POOL_SIZE) _pool.push(e);
|
|
257
|
+
}
|
|
131
258
|
}
|
|
132
259
|
|
|
260
|
+
|
|
133
261
|
// Main wrapper factory
|
|
134
262
|
// fn: function(syntheticEvent) { ... }
|
|
135
263
|
// opts: { capture: bool, passive: bool, once: bool, stopPropagationOnTrueReturn: bool }
|
package/src/hooks.jsx
CHANGED
|
@@ -457,21 +457,6 @@ export function useDeferredValue(value, initialValue)
|
|
|
457
457
|
return deferred;
|
|
458
458
|
}
|
|
459
459
|
|
|
460
|
-
|
|
461
|
-
/**
|
|
462
|
-
* Wraps a render function so that a parent can pass a `ref` into it.
|
|
463
|
-
* The forwarded `ref` is provided as the second argument to the render function: `(props, ref)`.
|
|
464
|
-
*
|
|
465
|
-
* @param {function(props: any, ref: any)} render
|
|
466
|
-
* The component render function that receives the props and the forwarded ref.
|
|
467
|
-
* @returns {}
|
|
468
|
-
*/
|
|
469
|
-
export function forwardRef(render)
|
|
470
|
-
{
|
|
471
|
-
return (props)=>render({...props, ref: undefined}, props.ref);
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
|
|
475
460
|
/**
|
|
476
461
|
* Customizes the value that is exposed to the parent when it uses a `ref` on a component created with `forwardRef`.
|
|
477
462
|
* The object returned by `factory` becomes the value of `ref.current` for object refs.
|
package/src/lilact.jsx
CHANGED
|
@@ -28,6 +28,26 @@
|
|
|
28
28
|
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
|
+
|
|
32
|
+
/*
|
|
33
|
+
note:
|
|
34
|
+
|
|
35
|
+
If you are reading the code, keep in my mind that in the development of `Lilact`,
|
|
36
|
+
I have used a naming convention that is a little different from the standard way:
|
|
37
|
+
|
|
38
|
+
I use underscored all lowercase names for internal variables.
|
|
39
|
+
I use all caps for constants that are used similar to C defined macros. e.g. shared
|
|
40
|
+
symbols.
|
|
41
|
+
|
|
42
|
+
And I use the standard convention for exposed user space variables and arguments, and
|
|
43
|
+
functions.
|
|
44
|
+
|
|
45
|
+
So if a variable name is in the format `aaa_bbb`, it means I am counting on it to be
|
|
46
|
+
used internally. And if it is `AAA_BBB`, I'm counting on it to be constant in the whole
|
|
47
|
+
application lifetime.
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
|
|
31
51
|
import * as redux from "redux";
|
|
32
52
|
import * as emotion from "@emotion/css";
|
|
33
53
|
import PropTypes from 'prop-types';
|
|
@@ -74,7 +94,7 @@ export {transpileJSX, transpilerConfig} from "./jsx";
|
|
|
74
94
|
export const Lilact =
|
|
75
95
|
{
|
|
76
96
|
|
|
77
|
-
VERSION: "beta.
|
|
97
|
+
VERSION: "beta.10",
|
|
78
98
|
|
|
79
99
|
// Configuration
|
|
80
100
|
|
|
@@ -108,7 +128,6 @@ export const Lilact =
|
|
|
108
128
|
emotion,
|
|
109
129
|
|
|
110
130
|
}
|
|
111
|
-
|
|
112
131
|
globalThis.Lilact = Lilact;
|
|
113
132
|
globalThis.createComponent = Lilact.createComponent;
|
|
114
133
|
globalThis.Fragment = Lilact.Fragment;
|
package/src/misc.jsx
CHANGED
|
@@ -143,6 +143,20 @@ export const Children = {
|
|
|
143
143
|
};
|
|
144
144
|
|
|
145
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Wraps a render function so that a parent can pass a `ref` into it.
|
|
148
|
+
* The forwarded `ref` is provided as the second argument to the render function: `(props, ref)`.
|
|
149
|
+
*
|
|
150
|
+
* @param {function(props: any, ref: any)} render
|
|
151
|
+
* The component render function that receives the props and the forwarded ref.
|
|
152
|
+
* @returns {}
|
|
153
|
+
*/
|
|
154
|
+
export function forwardRef(render)
|
|
155
|
+
{
|
|
156
|
+
return (props)=>render({...props, ref: undefined}, props.ref);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
|
|
146
160
|
/**
|
|
147
161
|
* Debug tool to detect the component visible at a point on screen.
|
|
148
162
|
*
|
package/src/pane.jsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useEffect, useLayoutEffect, useMemo, useRef, useState,
|
|
2
|
-
import { Children } from "./misc.jsx";
|
|
1
|
+
import { useEffect, useLayoutEffect, useMemo, useRef, useState, useImperativeHandle } from "./hooks.jsx";
|
|
2
|
+
import { Children, forwardRef } from "./misc.jsx";
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
const clamp = (n, min, max) => {
|
package/src/run.jsx
CHANGED
|
@@ -120,13 +120,13 @@ export function run(jsx, path=`InlineJSX-${++Lilact.eval_num}`, is_inline=true)
|
|
|
120
120
|
* @param path - The path to the required file. Must be either absolute path or relative to the current
|
|
121
121
|
* document’s URL (the page/location that initiated the request).
|
|
122
122
|
*
|
|
123
|
-
* @param
|
|
123
|
+
* @param forceUpdate - To treat the code as inline. The main difference at the moment is that inline code doesn't include sourcemap.
|
|
124
124
|
*
|
|
125
125
|
* @returns An array representation of the children.
|
|
126
126
|
*/
|
|
127
|
-
export function require(path,
|
|
127
|
+
export function require(path, forceUpdate)
|
|
128
128
|
{
|
|
129
|
-
if(Lilact.required_scripts[path] && !
|
|
129
|
+
if(Lilact.required_scripts[path] && !forceUpdate) return Lilact.required_scripts[path].module.exports;
|
|
130
130
|
|
|
131
131
|
if(path[0]==='#') {
|
|
132
132
|
|
|
@@ -178,7 +178,7 @@ export function require(path, force_update)
|
|
|
178
178
|
* The promise must resolve to a module whose module.exports.default is a Lilact component
|
|
179
179
|
* or otherwise it will be whatever the module.exports is set to.
|
|
180
180
|
*
|
|
181
|
-
* @returns A Lilact component that should be rendered inside a
|
|
181
|
+
* @returns A Lilact component that should be rendered inside a `Suspense` boundary.
|
|
182
182
|
*/
|
|
183
183
|
export function lazy(factory) {
|
|
184
184
|
let status = "pending"; // pending | success | error
|
package/src/timers.jsx
CHANGED
|
@@ -277,27 +277,27 @@ export function releaseTimers()
|
|
|
277
277
|
* @param {number} duration - Delay in milliseconds.
|
|
278
278
|
* @returns {Promise} Promise that resolves after the delay.
|
|
279
279
|
*/
|
|
280
|
-
export function timeoutPromise(duration=0,
|
|
280
|
+
export function timeoutPromise(duration=0, timerSource=this)
|
|
281
281
|
{
|
|
282
282
|
let id, resolve, reject;
|
|
283
283
|
|
|
284
284
|
const promise = new Promise((res, rej) => {
|
|
285
285
|
resolve = res;
|
|
286
286
|
reject = rej;
|
|
287
|
-
id =
|
|
287
|
+
id = timerSource.setTimeout(() => {
|
|
288
288
|
resolve();
|
|
289
289
|
}, duration);
|
|
290
290
|
});
|
|
291
291
|
|
|
292
292
|
// note: proceed interrupts the timer, and continues the flow if used with await.
|
|
293
293
|
promise.proceed = () => {
|
|
294
|
-
|
|
294
|
+
timerSource.clearTimeout(id);
|
|
295
295
|
resolve();
|
|
296
296
|
};
|
|
297
297
|
|
|
298
298
|
// note: cancel rejects so it throws exception when using with await, this allows handling it differently.
|
|
299
299
|
promise.cancel = () => {
|
|
300
|
-
|
|
300
|
+
timerSource.clearTimeout(id);
|
|
301
301
|
reject();
|
|
302
302
|
};
|
|
303
303
|
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>forwardRef | Lilact</title><meta name="description" content="Documentation for Lilact"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script><script async src="../assets/hierarchy.js" id="tsd-hierarchy-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">Lilact</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="../modules/hooks.html">hooks</a></li><li><a href="" aria-current="page">forwardRef</a></li></ul><h1>Function forwardRef</h1></div><section class="tsd-panel"><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="forwardref"><span class="tsd-kind-call-signature">forwardRef</span><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">render</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">any</span><a href="#forwardref" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>Wraps a render function so that a parent can pass a <code>ref</code> into it.
|
|
2
|
-
The forwarded <code>ref</code> is provided as the second argument to the render function: <code>(props, ref)</code>.</p>
|
|
3
|
-
</div><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">render</span>: <span class="tsd-signature-type">any</span></span><div class="tsd-comment tsd-typography"><p>The component render function that receives the props and the forwarded ref.</p>
|
|
4
|
-
</div></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">any</span></h4><aside class="tsd-sources"><ul><li>Defined in hooks.js:469</li></ul></aside></div></li></ul></section></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">Lilact</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
|