@sigx/runtime-terminal 0.1.5 → 0.1.7
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 +7 -7
- package/dist/components/Checkbox.d.ts +5 -2
- package/dist/components/Input.d.ts +5 -2
- package/dist/components/Select.d.ts +7 -2
- package/dist/index.d.ts +1 -3
- package/dist/index.js +69 -1359
- package/dist/index.js.map +1 -1
- package/package.json +8 -7
- package/dist/keyboard.d.ts +0 -4
package/dist/index.js
CHANGED
|
@@ -1,1002 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
function getComponentPlugins$1() {
|
|
7
|
-
return plugins$1;
|
|
8
|
-
}
|
|
9
|
-
const contextExtensions = [];
|
|
10
|
-
/**
|
|
11
|
-
* Apply all registered context extensions to a context object.
|
|
12
|
-
* Called internally by the renderer when creating component contexts.
|
|
13
|
-
*/
|
|
14
|
-
function applyContextExtensions(ctx) {
|
|
15
|
-
for (const extension of contextExtensions) extension(ctx);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
//#endregion
|
|
19
|
-
//#region ../runtime-core/src/app.ts
|
|
20
|
-
let defaultMountFn = null;
|
|
21
|
-
/**
|
|
22
|
-
* Set the default mount function for the platform.
|
|
23
|
-
* Called by platform packages (runtime-dom, runtime-terminal) on import.
|
|
24
|
-
*
|
|
25
|
-
* @example
|
|
26
|
-
* ```typescript
|
|
27
|
-
* // In @sigx/runtime-dom
|
|
28
|
-
* import { setDefaultMount } from '@sigx/runtime-core';
|
|
29
|
-
* setDefaultMount(domMount);
|
|
30
|
-
* ```
|
|
31
|
-
*/
|
|
32
|
-
function setDefaultMount(mountFn) {
|
|
33
|
-
defaultMountFn = mountFn;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Notify all app hooks that a component was created.
|
|
37
|
-
* Called by the renderer after setup() returns.
|
|
38
|
-
*/
|
|
39
|
-
function notifyComponentCreated(context, instance) {
|
|
40
|
-
if (!context) return;
|
|
41
|
-
for (const hooks of context.hooks) try {
|
|
42
|
-
hooks.onComponentCreated?.(instance);
|
|
43
|
-
} catch (err) {
|
|
44
|
-
handleHookError(context, err, instance, "onComponentCreated");
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Notify all app hooks that a component was mounted.
|
|
49
|
-
* Called by the renderer after mount hooks run.
|
|
50
|
-
*/
|
|
51
|
-
function notifyComponentMounted(context, instance) {
|
|
52
|
-
if (!context) return;
|
|
53
|
-
for (const hooks of context.hooks) try {
|
|
54
|
-
hooks.onComponentMounted?.(instance);
|
|
55
|
-
} catch (err) {
|
|
56
|
-
handleHookError(context, err, instance, "onComponentMounted");
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Notify all app hooks that a component was unmounted.
|
|
61
|
-
* Called by the renderer before cleanup.
|
|
62
|
-
*/
|
|
63
|
-
function notifyComponentUnmounted(context, instance) {
|
|
64
|
-
if (!context) return;
|
|
65
|
-
for (const hooks of context.hooks) try {
|
|
66
|
-
hooks.onComponentUnmounted?.(instance);
|
|
67
|
-
} catch (err) {
|
|
68
|
-
handleHookError(context, err, instance, "onComponentUnmounted");
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Notify all app hooks that a component updated.
|
|
73
|
-
* Called by the renderer after re-render.
|
|
74
|
-
*/
|
|
75
|
-
function notifyComponentUpdated(context, instance) {
|
|
76
|
-
if (!context) return;
|
|
77
|
-
for (const hooks of context.hooks) try {
|
|
78
|
-
hooks.onComponentUpdated?.(instance);
|
|
79
|
-
} catch (err) {
|
|
80
|
-
handleHookError(context, err, instance, "onComponentUpdated");
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Handle an error in a component. Returns true if the error was handled.
|
|
85
|
-
* Called by the renderer when an error occurs in setup or render.
|
|
86
|
-
*/
|
|
87
|
-
function handleComponentError(context, err, instance, info) {
|
|
88
|
-
if (!context) return false;
|
|
89
|
-
for (const hooks of context.hooks) try {
|
|
90
|
-
if (hooks.onComponentError?.(err, instance, info) === true) return true;
|
|
91
|
-
} catch (hookErr) {
|
|
92
|
-
console.error("Error in onComponentError hook:", hookErr);
|
|
93
|
-
}
|
|
94
|
-
if (context.config.errorHandler) try {
|
|
95
|
-
if (context.config.errorHandler(err, instance, info) === true) return true;
|
|
96
|
-
} catch (handlerErr) {
|
|
97
|
-
console.error("Error in app.config.errorHandler:", handlerErr);
|
|
98
|
-
}
|
|
99
|
-
return false;
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Handle errors that occur in hooks themselves
|
|
103
|
-
*/
|
|
104
|
-
function handleHookError(context, err, instance, hookName) {
|
|
105
|
-
console.error(`Error in ${hookName} hook:`, err);
|
|
106
|
-
if (context.config.errorHandler) try {
|
|
107
|
-
context.config.errorHandler(err, instance, `plugin hook: ${hookName}`);
|
|
108
|
-
} catch {}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
//#endregion
|
|
112
|
-
//#region ../runtime-core/src/component.ts
|
|
113
|
-
let currentComponentContext = null;
|
|
114
|
-
function getCurrentInstance() {
|
|
115
|
-
return currentComponentContext;
|
|
116
|
-
}
|
|
117
|
-
function setCurrentInstance(ctx) {
|
|
118
|
-
const prev = currentComponentContext;
|
|
119
|
-
currentComponentContext = ctx;
|
|
120
|
-
return prev;
|
|
121
|
-
}
|
|
122
|
-
function onMount(fn) {
|
|
123
|
-
if (currentComponentContext) currentComponentContext.onMount(fn);
|
|
124
|
-
else console.warn("onMount called outside of component setup");
|
|
125
|
-
}
|
|
126
|
-
function onCleanup(fn) {
|
|
127
|
-
if (currentComponentContext) currentComponentContext.onCleanup(fn);
|
|
128
|
-
else console.warn("onCleanup called outside of component setup");
|
|
129
|
-
}
|
|
130
|
-
const componentRegistry$1 = /* @__PURE__ */ new Map();
|
|
131
|
-
/**
|
|
132
|
-
* Define a component. Returns a JSX factory function.
|
|
133
|
-
*
|
|
134
|
-
* @param setup - Setup function that receives context and returns a render function
|
|
135
|
-
* @param options - Optional configuration (e.g., name for DevTools)
|
|
136
|
-
*
|
|
137
|
-
* @example
|
|
138
|
-
* ```tsx
|
|
139
|
-
* type CardProps = DefineProp<"title", string> & DefineSlot<"header">;
|
|
140
|
-
*
|
|
141
|
-
* export const Card = defineComponent<CardProps>((ctx) => {
|
|
142
|
-
* const { title } = ctx.props;
|
|
143
|
-
* const { slots } = ctx;
|
|
144
|
-
*
|
|
145
|
-
* return () => (
|
|
146
|
-
* <div class="card">
|
|
147
|
-
* {slots.header?.() ?? <h2>{title}</h2>}
|
|
148
|
-
* {slots.default()}
|
|
149
|
-
* </div>
|
|
150
|
-
* );
|
|
151
|
-
* });
|
|
152
|
-
* ```
|
|
153
|
-
*/
|
|
154
|
-
function defineComponent(setup, options) {
|
|
155
|
-
const factory = function(props) {
|
|
156
|
-
return {
|
|
157
|
-
type: factory,
|
|
158
|
-
props: props || {},
|
|
159
|
-
key: props?.key || null,
|
|
160
|
-
children: [],
|
|
161
|
-
dom: null
|
|
162
|
-
};
|
|
163
|
-
};
|
|
164
|
-
factory.__setup = setup;
|
|
165
|
-
factory.__name = options?.name;
|
|
166
|
-
factory.__props = null;
|
|
167
|
-
factory.__events = null;
|
|
168
|
-
factory.__ref = null;
|
|
169
|
-
factory.__slots = null;
|
|
170
|
-
componentRegistry$1.set(factory, {
|
|
171
|
-
name: options?.name,
|
|
172
|
-
setup
|
|
173
|
-
});
|
|
174
|
-
getComponentPlugins$1().forEach((p) => p.onDefine?.(options?.name, factory, setup));
|
|
175
|
-
return factory;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
//#endregion
|
|
179
|
-
//#region ../reactivity/src/index.ts
|
|
180
|
-
let activeEffect = null;
|
|
181
|
-
let batchDepth = 0;
|
|
182
|
-
const pendingEffects = /* @__PURE__ */ new Set();
|
|
183
|
-
function batch(fn) {
|
|
184
|
-
batchDepth++;
|
|
185
|
-
try {
|
|
186
|
-
fn();
|
|
187
|
-
} finally {
|
|
188
|
-
batchDepth--;
|
|
189
|
-
if (batchDepth === 0) {
|
|
190
|
-
const effects = Array.from(pendingEffects);
|
|
191
|
-
pendingEffects.clear();
|
|
192
|
-
for (const effect$1 of effects) effect$1();
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
function runEffect(fn) {
|
|
197
|
-
const effectFn = function() {
|
|
198
|
-
cleanup(effectFn);
|
|
199
|
-
activeEffect = effectFn;
|
|
200
|
-
fn();
|
|
201
|
-
activeEffect = null;
|
|
202
|
-
};
|
|
203
|
-
effectFn.deps = [];
|
|
204
|
-
effectFn();
|
|
205
|
-
const runner = (() => effectFn());
|
|
206
|
-
runner.stop = () => cleanup(effectFn);
|
|
207
|
-
return runner;
|
|
208
|
-
}
|
|
209
|
-
function cleanup(effect$1) {
|
|
210
|
-
if (!effect$1.deps) return;
|
|
211
|
-
for (const dep of effect$1.deps) dep.delete(effect$1);
|
|
212
|
-
effect$1.deps.length = 0;
|
|
213
|
-
}
|
|
214
|
-
function track(depSet) {
|
|
215
|
-
if (!activeEffect) return;
|
|
216
|
-
depSet.add(activeEffect);
|
|
217
|
-
activeEffect.deps.push(depSet);
|
|
218
|
-
}
|
|
219
|
-
function trigger(depSet) {
|
|
220
|
-
const effects = Array.from(depSet);
|
|
221
|
-
for (const effect$1 of effects) if (batchDepth > 0) pendingEffects.add(effect$1);
|
|
222
|
-
else effect$1();
|
|
223
|
-
}
|
|
224
|
-
let accessObserver = null;
|
|
225
|
-
function detectAccess(selector) {
|
|
226
|
-
let result = null;
|
|
227
|
-
const prev = accessObserver;
|
|
228
|
-
accessObserver = (target, key) => {
|
|
229
|
-
result = [target, key];
|
|
230
|
-
};
|
|
231
|
-
try {
|
|
232
|
-
selector();
|
|
233
|
-
} finally {
|
|
234
|
-
accessObserver = prev;
|
|
235
|
-
}
|
|
236
|
-
return result;
|
|
237
|
-
}
|
|
238
|
-
function untrack(fn) {
|
|
239
|
-
const prev = activeEffect;
|
|
240
|
-
activeEffect = null;
|
|
241
|
-
try {
|
|
242
|
-
return fn();
|
|
243
|
-
} finally {
|
|
244
|
-
activeEffect = prev;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
function signal(target) {
|
|
248
|
-
const depsMap = /* @__PURE__ */ new Map();
|
|
249
|
-
const reactiveCache = /* @__PURE__ */ new WeakMap();
|
|
250
|
-
return new Proxy(target, {
|
|
251
|
-
get(obj, prop, receiver) {
|
|
252
|
-
if (prop === "$set") return (newValue) => {
|
|
253
|
-
batch(() => {
|
|
254
|
-
if (Array.isArray(obj) && Array.isArray(newValue)) {
|
|
255
|
-
const len = newValue.length;
|
|
256
|
-
for (let i = 0; i < len; i++) Reflect.set(receiver, String(i), newValue[i]);
|
|
257
|
-
Reflect.set(receiver, "length", len);
|
|
258
|
-
} else {
|
|
259
|
-
const newKeys = Object.keys(newValue);
|
|
260
|
-
const oldKeys = Object.keys(obj);
|
|
261
|
-
for (const key of newKeys) Reflect.set(receiver, key, newValue[key]);
|
|
262
|
-
for (const key of oldKeys) if (!(key in newValue)) Reflect.deleteProperty(receiver, key);
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
};
|
|
266
|
-
if (Array.isArray(obj) && typeof prop === "string" && arrayInstrumentations.hasOwnProperty(prop)) return arrayInstrumentations[prop];
|
|
267
|
-
const value = Reflect.get(obj, prop);
|
|
268
|
-
if (accessObserver) accessObserver(receiver, prop);
|
|
269
|
-
let dep = depsMap.get(prop);
|
|
270
|
-
if (!dep) {
|
|
271
|
-
dep = /* @__PURE__ */ new Set();
|
|
272
|
-
depsMap.set(prop, dep);
|
|
273
|
-
}
|
|
274
|
-
track(dep);
|
|
275
|
-
if (value && typeof value === "object") {
|
|
276
|
-
let cached = reactiveCache.get(value);
|
|
277
|
-
if (!cached) {
|
|
278
|
-
cached = signal(value);
|
|
279
|
-
reactiveCache.set(value, cached);
|
|
280
|
-
}
|
|
281
|
-
return cached;
|
|
282
|
-
}
|
|
283
|
-
return value;
|
|
284
|
-
},
|
|
285
|
-
set(obj, prop, newValue) {
|
|
286
|
-
const oldLength = Array.isArray(obj) ? obj.length : 0;
|
|
287
|
-
const oldValue = Reflect.get(obj, prop);
|
|
288
|
-
const result = Reflect.set(obj, prop, newValue);
|
|
289
|
-
if (!Object.is(oldValue, newValue)) {
|
|
290
|
-
const dep = depsMap.get(prop);
|
|
291
|
-
if (dep) trigger(dep);
|
|
292
|
-
if (Array.isArray(obj)) {
|
|
293
|
-
if (prop !== "length" && obj.length !== oldLength) {
|
|
294
|
-
const lengthDep = depsMap.get("length");
|
|
295
|
-
if (lengthDep) trigger(lengthDep);
|
|
296
|
-
}
|
|
297
|
-
if (prop === "length" && typeof newValue === "number" && newValue < oldLength) for (let i = newValue; i < oldLength; i++) {
|
|
298
|
-
const idxDep = depsMap.get(String(i));
|
|
299
|
-
if (idxDep) trigger(idxDep);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
return result;
|
|
304
|
-
},
|
|
305
|
-
deleteProperty(obj, prop) {
|
|
306
|
-
const hasKey = Object.prototype.hasOwnProperty.call(obj, prop);
|
|
307
|
-
const result = Reflect.deleteProperty(obj, prop);
|
|
308
|
-
if (result && hasKey) {
|
|
309
|
-
const dep = depsMap.get(prop);
|
|
310
|
-
if (dep) trigger(dep);
|
|
311
|
-
}
|
|
312
|
-
return result;
|
|
313
|
-
}
|
|
314
|
-
});
|
|
315
|
-
}
|
|
316
|
-
function effect(fn) {
|
|
317
|
-
return runEffect(fn);
|
|
318
|
-
}
|
|
319
|
-
const arrayInstrumentations = {};
|
|
320
|
-
[
|
|
321
|
-
"push",
|
|
322
|
-
"pop",
|
|
323
|
-
"shift",
|
|
324
|
-
"unshift",
|
|
325
|
-
"splice",
|
|
326
|
-
"sort",
|
|
327
|
-
"reverse"
|
|
328
|
-
].forEach((method) => {
|
|
329
|
-
arrayInstrumentations[method] = function(...args) {
|
|
330
|
-
let res;
|
|
331
|
-
batch(() => {
|
|
332
|
-
res = Array.prototype[method].apply(this, args);
|
|
333
|
-
});
|
|
334
|
-
return res;
|
|
335
|
-
};
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
//#endregion
|
|
339
|
-
//#region ../runtime-core/src/jsx-runtime.ts
|
|
340
|
-
const Fragment$1 = Symbol.for("sigx.Fragment");
|
|
341
|
-
const Text$1 = Symbol.for("sigx.Text");
|
|
342
|
-
|
|
343
|
-
//#endregion
|
|
344
|
-
//#region ../runtime-core/src/lazy.tsx
|
|
345
|
-
/**
|
|
346
|
-
* Lazy loading utilities for sigx components.
|
|
347
|
-
*
|
|
348
|
-
* Provides runtime-only lazy loading with no build dependencies.
|
|
349
|
-
* Works with any bundler that supports dynamic import().
|
|
350
|
-
*/
|
|
351
|
-
let currentSuspenseBoundary$1 = null;
|
|
352
|
-
/**
|
|
353
|
-
* Register a promise with the current Suspense boundary
|
|
354
|
-
* @internal
|
|
355
|
-
*/
|
|
356
|
-
function registerPendingPromise$1(promise) {
|
|
357
|
-
const boundary = currentSuspenseBoundary$1;
|
|
358
|
-
if (boundary) {
|
|
359
|
-
boundary.pending.add(promise);
|
|
360
|
-
promise.finally(() => {
|
|
361
|
-
boundary.pending.delete(promise);
|
|
362
|
-
if (boundary.pending.size === 0) boundary.onResolve();
|
|
363
|
-
});
|
|
364
|
-
return true;
|
|
365
|
-
}
|
|
366
|
-
return false;
|
|
367
|
-
}
|
|
368
|
-
/**
|
|
369
|
-
* Suspense boundary component for handling async loading states.
|
|
370
|
-
*
|
|
371
|
-
* Wraps lazy-loaded components and shows a fallback while they load.
|
|
372
|
-
*
|
|
373
|
-
* @example
|
|
374
|
-
* ```tsx
|
|
375
|
-
* import { lazy, Suspense } from 'sigx';
|
|
376
|
-
*
|
|
377
|
-
* const LazyDashboard = lazy(() => import('./Dashboard'));
|
|
378
|
-
*
|
|
379
|
-
* // Basic usage
|
|
380
|
-
* <Suspense fallback={<div>Loading...</div>}>
|
|
381
|
-
* <LazyDashboard />
|
|
382
|
-
* </Suspense>
|
|
383
|
-
*
|
|
384
|
-
* // With spinner component
|
|
385
|
-
* <Suspense fallback={<Spinner size="large" />}>
|
|
386
|
-
* <LazyDashboard />
|
|
387
|
-
* <LazyCharts />
|
|
388
|
-
* </Suspense>
|
|
389
|
-
* ```
|
|
390
|
-
*/
|
|
391
|
-
const Suspense$1 = defineComponent((ctx) => {
|
|
392
|
-
const { props, slots } = ctx;
|
|
393
|
-
const state = ctx.signal({
|
|
394
|
-
isReady: false,
|
|
395
|
-
pendingCount: 0
|
|
396
|
-
});
|
|
397
|
-
const boundary = {
|
|
398
|
-
pending: /* @__PURE__ */ new Set(),
|
|
399
|
-
onResolve: () => {
|
|
400
|
-
state.pendingCount = boundary.pending.size;
|
|
401
|
-
if (boundary.pending.size === 0) state.isReady = true;
|
|
402
|
-
}
|
|
403
|
-
};
|
|
404
|
-
ctx.onMount(() => {
|
|
405
|
-
if (boundary.pending.size === 0) state.isReady = true;
|
|
406
|
-
});
|
|
407
|
-
return () => {
|
|
408
|
-
state.isReady;
|
|
409
|
-
state.pendingCount;
|
|
410
|
-
const prevBoundary = currentSuspenseBoundary$1;
|
|
411
|
-
currentSuspenseBoundary$1 = boundary;
|
|
412
|
-
try {
|
|
413
|
-
const children = slots.default();
|
|
414
|
-
if (boundary.pending.size > 0) {
|
|
415
|
-
const fallback = props.fallback;
|
|
416
|
-
if (typeof fallback === "function") return fallback();
|
|
417
|
-
return fallback ?? null;
|
|
418
|
-
}
|
|
419
|
-
if (Array.isArray(children)) {
|
|
420
|
-
const filtered = children.filter((c) => c != null && c !== false && c !== true);
|
|
421
|
-
if (filtered.length === 0) return null;
|
|
422
|
-
if (filtered.length === 1) return filtered[0];
|
|
423
|
-
return filtered;
|
|
424
|
-
}
|
|
425
|
-
return children;
|
|
426
|
-
} catch (err) {
|
|
427
|
-
if (err instanceof Promise) {
|
|
428
|
-
registerPendingPromise$1(err);
|
|
429
|
-
const fallback = props.fallback;
|
|
430
|
-
if (typeof fallback === "function") return fallback();
|
|
431
|
-
return fallback ?? null;
|
|
432
|
-
}
|
|
433
|
-
throw err;
|
|
434
|
-
} finally {
|
|
435
|
-
currentSuspenseBoundary$1 = prevBoundary;
|
|
436
|
-
}
|
|
437
|
-
};
|
|
438
|
-
}, { name: "Suspense" });
|
|
439
|
-
|
|
440
|
-
//#endregion
|
|
441
|
-
//#region ../runtime-core/src/utils/props-accessor.ts
|
|
442
|
-
/**
|
|
443
|
-
* Creates a props accessor that can be called with defaults or accessed directly.
|
|
444
|
-
* After calling with defaults, direct property access uses those defaults.
|
|
445
|
-
*
|
|
446
|
-
* @example
|
|
447
|
-
* ```ts
|
|
448
|
-
* // In component setup:
|
|
449
|
-
* const props = createPropsAccessor(reactiveProps);
|
|
450
|
-
*
|
|
451
|
-
* // Set defaults
|
|
452
|
-
* props({ count: 0, label: 'Default' });
|
|
453
|
-
*
|
|
454
|
-
* // Access props (falls back to defaults if not provided)
|
|
455
|
-
* const count = props.count;
|
|
456
|
-
* ```
|
|
457
|
-
*/
|
|
458
|
-
function createPropsAccessor(reactiveProps) {
|
|
459
|
-
let defaults = {};
|
|
460
|
-
const proxy = new Proxy(function propsAccessor() {}, {
|
|
461
|
-
get(_, key) {
|
|
462
|
-
if (typeof key === "symbol") return void 0;
|
|
463
|
-
const value = reactiveProps[key];
|
|
464
|
-
return value != null ? value : defaults[key];
|
|
465
|
-
},
|
|
466
|
-
apply(_, __, args) {
|
|
467
|
-
if (args[0] && typeof args[0] === "object") defaults = {
|
|
468
|
-
...defaults,
|
|
469
|
-
...args[0]
|
|
470
|
-
};
|
|
471
|
-
return proxy;
|
|
472
|
-
},
|
|
473
|
-
has(_, key) {
|
|
474
|
-
if (typeof key === "symbol") return false;
|
|
475
|
-
return key in reactiveProps || key in defaults;
|
|
476
|
-
},
|
|
477
|
-
ownKeys() {
|
|
478
|
-
return [...new Set([...Object.keys(reactiveProps), ...Object.keys(defaults)])];
|
|
479
|
-
},
|
|
480
|
-
getOwnPropertyDescriptor(_, key) {
|
|
481
|
-
if (typeof key === "symbol") return void 0;
|
|
482
|
-
if (key in reactiveProps || key in defaults) return {
|
|
483
|
-
enumerable: true,
|
|
484
|
-
configurable: true,
|
|
485
|
-
writable: false
|
|
486
|
-
};
|
|
487
|
-
}
|
|
488
|
-
});
|
|
489
|
-
return proxy;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
//#endregion
|
|
493
|
-
//#region ../runtime-core/src/utils/slots.ts
|
|
494
|
-
/**
|
|
495
|
-
* Slots system for component children.
|
|
496
|
-
* Supports default and named slots with reactivity.
|
|
497
|
-
*/
|
|
498
|
-
/**
|
|
499
|
-
* Create slots object from children and slots prop.
|
|
500
|
-
* Uses a version signal to trigger re-renders when children change.
|
|
501
|
-
*
|
|
502
|
-
* Supports named slots via:
|
|
503
|
-
* - `slots` prop object (e.g., `slots={{ header: () => <div>...</div> }}`)
|
|
504
|
-
* - `slot` prop on children (e.g., `<div slot="header">...</div>`)
|
|
505
|
-
*
|
|
506
|
-
* @example
|
|
507
|
-
* ```tsx
|
|
508
|
-
* // Parent component
|
|
509
|
-
* <Card slots={{ header: () => <h1>Title</h1> }}>
|
|
510
|
-
* <p>Default content</p>
|
|
511
|
-
* <span slot="footer">Footer text</span>
|
|
512
|
-
* </Card>
|
|
513
|
-
*
|
|
514
|
-
* // Card component setup
|
|
515
|
-
* const slots = createSlots(children, slotsFromProps);
|
|
516
|
-
* return () => (
|
|
517
|
-
* <div>
|
|
518
|
-
* {slots.header()}
|
|
519
|
-
* {slots.default()}
|
|
520
|
-
* {slots.footer()}
|
|
521
|
-
* </div>
|
|
522
|
-
* );
|
|
523
|
-
* ```
|
|
524
|
-
*/
|
|
525
|
-
function createSlots(children, slotsFromProps) {
|
|
526
|
-
const versionSignal = signal({ v: 0 });
|
|
527
|
-
function extractNamedSlotsFromChildren(c) {
|
|
528
|
-
const defaultChildren = [];
|
|
529
|
-
const namedSlots = {};
|
|
530
|
-
if (c == null) return {
|
|
531
|
-
defaultChildren,
|
|
532
|
-
namedSlots
|
|
533
|
-
};
|
|
534
|
-
const items = Array.isArray(c) ? c : [c];
|
|
535
|
-
for (const child of items) if (child && typeof child === "object" && child.props && child.props.slot) {
|
|
536
|
-
const slotName = child.props.slot;
|
|
537
|
-
if (!namedSlots[slotName]) namedSlots[slotName] = [];
|
|
538
|
-
namedSlots[slotName].push(child);
|
|
539
|
-
} else defaultChildren.push(child);
|
|
540
|
-
return {
|
|
541
|
-
defaultChildren,
|
|
542
|
-
namedSlots
|
|
543
|
-
};
|
|
544
|
-
}
|
|
545
|
-
const slotsObj = {
|
|
546
|
-
_children: children,
|
|
547
|
-
_slotsFromProps: slotsFromProps || {},
|
|
548
|
-
_version: versionSignal,
|
|
549
|
-
_isPatching: false,
|
|
550
|
-
default: function() {
|
|
551
|
-
this._version.v;
|
|
552
|
-
const c = this._children;
|
|
553
|
-
const { defaultChildren } = extractNamedSlotsFromChildren(c);
|
|
554
|
-
return defaultChildren.filter((child) => child != null && child !== false && child !== true);
|
|
555
|
-
}
|
|
556
|
-
};
|
|
557
|
-
return new Proxy(slotsObj, { get(target, prop) {
|
|
558
|
-
if (prop in target) return target[prop];
|
|
559
|
-
if (typeof prop === "string") return function(scopedProps) {
|
|
560
|
-
target._version.v;
|
|
561
|
-
if (target._slotsFromProps && typeof target._slotsFromProps[prop] === "function") {
|
|
562
|
-
const result = target._slotsFromProps[prop](scopedProps);
|
|
563
|
-
if (result == null) return [];
|
|
564
|
-
return Array.isArray(result) ? result : [result];
|
|
565
|
-
}
|
|
566
|
-
const { namedSlots } = extractNamedSlotsFromChildren(target._children);
|
|
567
|
-
return namedSlots[prop] || [];
|
|
568
|
-
};
|
|
569
|
-
} });
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
//#endregion
|
|
573
|
-
//#region ../runtime-core/src/utils/normalize.ts
|
|
574
|
-
/**
|
|
575
|
-
* VNode normalization utilities.
|
|
576
|
-
* Converts render results into proper VNode structures.
|
|
577
|
-
*/
|
|
578
|
-
/**
|
|
579
|
-
* Normalize render result to a VNode (wrapping arrays in Fragment).
|
|
580
|
-
* Handles null, undefined, false, true by returning an empty Text node.
|
|
581
|
-
*
|
|
582
|
-
* This is used to normalize the return value of component render functions
|
|
583
|
-
* into a consistent VNode structure for the renderer to process.
|
|
584
|
-
*
|
|
585
|
-
* @example
|
|
586
|
-
* ```ts
|
|
587
|
-
* // Conditional rendering returns null/false
|
|
588
|
-
* normalizeSubTree(null) // → empty Text node
|
|
589
|
-
* normalizeSubTree(false) // → empty Text node
|
|
590
|
-
*
|
|
591
|
-
* // Arrays become Fragments
|
|
592
|
-
* normalizeSubTree([<A/>, <B/>]) // → Fragment with children
|
|
593
|
-
*
|
|
594
|
-
* // Primitives become Text nodes
|
|
595
|
-
* normalizeSubTree("hello") // → Text node
|
|
596
|
-
* normalizeSubTree(42) // → Text node
|
|
597
|
-
*
|
|
598
|
-
* // VNodes pass through
|
|
599
|
-
* normalizeSubTree(<div/>) // → same VNode
|
|
600
|
-
* ```
|
|
601
|
-
*/
|
|
602
|
-
function normalizeSubTree(result) {
|
|
603
|
-
if (result == null || result === false || result === true) return {
|
|
604
|
-
type: Text$1,
|
|
605
|
-
props: {},
|
|
606
|
-
key: null,
|
|
607
|
-
children: [],
|
|
608
|
-
dom: null,
|
|
609
|
-
text: ""
|
|
610
|
-
};
|
|
611
|
-
if (Array.isArray(result)) return {
|
|
612
|
-
type: Fragment$1,
|
|
613
|
-
props: {},
|
|
614
|
-
key: null,
|
|
615
|
-
children: result,
|
|
616
|
-
dom: null
|
|
617
|
-
};
|
|
618
|
-
if (typeof result === "string" || typeof result === "number") return {
|
|
619
|
-
type: Text$1,
|
|
620
|
-
props: {},
|
|
621
|
-
key: null,
|
|
622
|
-
children: [],
|
|
623
|
-
dom: null,
|
|
624
|
-
text: result
|
|
625
|
-
};
|
|
626
|
-
return result;
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
//#endregion
|
|
630
|
-
//#region ../runtime-core/src/renderer.ts
|
|
631
|
-
/**
|
|
632
|
-
* Check if a vnode type is a component (has __setup)
|
|
633
|
-
*/
|
|
634
|
-
function isComponent(type) {
|
|
635
|
-
return typeof type === "function" && "__setup" in type;
|
|
636
|
-
}
|
|
637
|
-
function createRenderer(options) {
|
|
638
|
-
const { insert: hostInsert, remove: hostRemove, patchProp: hostPatchProp, createElement: hostCreateElement, createText: hostCreateText, createComment: hostCreateComment, setText: hostSetText, setElementText: hostSetElementText, parentNode: hostParentNode, nextSibling: hostNextSibling, cloneNode: hostCloneNode, insertStaticContent: hostInsertStaticContent } = options;
|
|
639
|
-
let currentAppContext = null;
|
|
640
|
-
function render$1(element, container, appContext) {
|
|
641
|
-
if (appContext) currentAppContext = appContext;
|
|
642
|
-
const oldVNode = container._vnode;
|
|
643
|
-
let vnode = null;
|
|
644
|
-
if (element != null && element !== false && element !== true) if (typeof element === "string" || typeof element === "number") vnode = {
|
|
645
|
-
type: Text$1,
|
|
646
|
-
props: {},
|
|
647
|
-
key: null,
|
|
648
|
-
children: [],
|
|
649
|
-
dom: null,
|
|
650
|
-
text: element
|
|
651
|
-
};
|
|
652
|
-
else if (isComponent(element)) vnode = {
|
|
653
|
-
type: element,
|
|
654
|
-
props: {},
|
|
655
|
-
key: null,
|
|
656
|
-
children: [],
|
|
657
|
-
dom: null
|
|
658
|
-
};
|
|
659
|
-
else vnode = element;
|
|
660
|
-
if (vnode) {
|
|
661
|
-
if (oldVNode) patch(oldVNode, vnode, container);
|
|
662
|
-
else mount(vnode, container);
|
|
663
|
-
container._vnode = vnode;
|
|
664
|
-
} else if (oldVNode) {
|
|
665
|
-
unmount(oldVNode, container);
|
|
666
|
-
container._vnode = null;
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
function mount(vnode, container, before = null) {
|
|
670
|
-
if (vnode == null || vnode === false || vnode === true) return;
|
|
671
|
-
if (vnode.type === Text$1) {
|
|
672
|
-
const node = hostCreateText(String(vnode.text));
|
|
673
|
-
vnode.dom = node;
|
|
674
|
-
node.__vnode = vnode;
|
|
675
|
-
hostInsert(node, container, before);
|
|
676
|
-
return;
|
|
677
|
-
}
|
|
678
|
-
if (vnode.type === Fragment$1) {
|
|
679
|
-
const anchor = hostCreateComment("");
|
|
680
|
-
vnode.dom = anchor;
|
|
681
|
-
hostInsert(anchor, container, before);
|
|
682
|
-
if (vnode.children) vnode.children.forEach((child) => mount(child, container, anchor));
|
|
683
|
-
return;
|
|
684
|
-
}
|
|
685
|
-
if (isComponent(vnode.type)) {
|
|
686
|
-
mountComponent(vnode, container, before, vnode.type.__setup);
|
|
687
|
-
return;
|
|
688
|
-
}
|
|
689
|
-
const element = hostCreateElement(vnode.type);
|
|
690
|
-
vnode.dom = element;
|
|
691
|
-
element.__vnode = vnode;
|
|
692
|
-
if (vnode.props) {
|
|
693
|
-
for (const key in vnode.props) if (key !== "children" && key !== "key" && key !== "ref") hostPatchProp(element, key, null, vnode.props[key]);
|
|
694
|
-
if (vnode.props.ref) {
|
|
695
|
-
if (typeof vnode.props.ref === "function") vnode.props.ref(element);
|
|
696
|
-
else if (typeof vnode.props.ref === "object") vnode.props.ref.current = element;
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
if (vnode.children) vnode.children.forEach((child) => {
|
|
700
|
-
child.parent = vnode;
|
|
701
|
-
mount(child, element);
|
|
702
|
-
});
|
|
703
|
-
hostInsert(element, container, before);
|
|
704
|
-
}
|
|
705
|
-
function unmount(vnode, container) {
|
|
706
|
-
const internalVNode = vnode;
|
|
707
|
-
if (internalVNode._effect) internalVNode._effect.stop();
|
|
708
|
-
if (vnode.cleanup) vnode.cleanup();
|
|
709
|
-
if (isComponent(vnode.type)) {
|
|
710
|
-
const subTree = internalVNode._subTree;
|
|
711
|
-
if (subTree) unmount(subTree, container);
|
|
712
|
-
if (vnode.dom) hostRemove(vnode.dom);
|
|
713
|
-
if (vnode.props?.ref) {
|
|
714
|
-
if (typeof vnode.props.ref === "function") vnode.props.ref(null);
|
|
715
|
-
else if (typeof vnode.props.ref === "object") vnode.props.ref.current = null;
|
|
716
|
-
}
|
|
717
|
-
return;
|
|
718
|
-
}
|
|
719
|
-
if (vnode.type === Fragment$1) {
|
|
720
|
-
if (vnode.children) vnode.children.forEach((child) => unmount(child, container));
|
|
721
|
-
if (vnode.dom) hostRemove(vnode.dom);
|
|
722
|
-
return;
|
|
723
|
-
}
|
|
724
|
-
if (vnode.props?.ref) {
|
|
725
|
-
if (typeof vnode.props.ref === "function") vnode.props.ref(null);
|
|
726
|
-
else if (vnode.props.ref && typeof vnode.props.ref === "object") vnode.props.ref.current = null;
|
|
727
|
-
}
|
|
728
|
-
if (vnode.children && vnode.children.length > 0) vnode.children.forEach((child) => unmount(child, vnode.dom));
|
|
729
|
-
if (vnode.dom) hostRemove(vnode.dom);
|
|
730
|
-
}
|
|
731
|
-
function patch(oldVNode, newVNode, container) {
|
|
732
|
-
if (oldVNode === newVNode) return;
|
|
733
|
-
if (!isSameVNode(oldVNode, newVNode)) {
|
|
734
|
-
const parent = hostParentNode(oldVNode.dom) || container;
|
|
735
|
-
const nextSibling = hostNextSibling(oldVNode.dom);
|
|
736
|
-
unmount(oldVNode, parent);
|
|
737
|
-
mount(newVNode, parent, nextSibling);
|
|
738
|
-
return;
|
|
739
|
-
}
|
|
740
|
-
const oldInternal = oldVNode;
|
|
741
|
-
const newInternal = newVNode;
|
|
742
|
-
if (oldInternal._effect) {
|
|
743
|
-
newVNode.dom = oldVNode.dom;
|
|
744
|
-
newInternal._effect = oldInternal._effect;
|
|
745
|
-
newInternal._subTree = oldInternal._subTree;
|
|
746
|
-
newInternal._slots = oldInternal._slots;
|
|
747
|
-
const props = oldInternal._componentProps;
|
|
748
|
-
newInternal._componentProps = props;
|
|
749
|
-
if (props) {
|
|
750
|
-
const newProps$1 = newVNode.props || {};
|
|
751
|
-
untrack(() => {
|
|
752
|
-
for (const key in newProps$1) if (key !== "children" && key !== "key" && key !== "ref") {
|
|
753
|
-
if (props[key] !== newProps$1[key]) props[key] = newProps$1[key];
|
|
754
|
-
}
|
|
755
|
-
for (const key in props) if (!(key in newProps$1) && key !== "children" && key !== "key" && key !== "ref") delete props[key];
|
|
756
|
-
});
|
|
757
|
-
}
|
|
758
|
-
const slotsRef = oldInternal._slots;
|
|
759
|
-
const newChildren = newVNode.props?.children;
|
|
760
|
-
const newSlotsFromProps = newVNode.props?.slots;
|
|
761
|
-
if (slotsRef) {
|
|
762
|
-
if (newChildren !== void 0) slotsRef._children = newChildren;
|
|
763
|
-
if (newSlotsFromProps !== void 0) slotsRef._slotsFromProps = newSlotsFromProps;
|
|
764
|
-
if (!slotsRef._isPatching) {
|
|
765
|
-
slotsRef._isPatching = true;
|
|
766
|
-
try {
|
|
767
|
-
untrack(() => {
|
|
768
|
-
slotsRef._version.v++;
|
|
769
|
-
});
|
|
770
|
-
} finally {
|
|
771
|
-
slotsRef._isPatching = false;
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
return;
|
|
776
|
-
}
|
|
777
|
-
if (newVNode.type === Text$1) {
|
|
778
|
-
newVNode.dom = oldVNode.dom;
|
|
779
|
-
if (oldVNode.text !== newVNode.text) hostSetText(newVNode.dom, String(newVNode.text));
|
|
780
|
-
return;
|
|
781
|
-
}
|
|
782
|
-
if (newVNode.type === Fragment$1) {
|
|
783
|
-
patchChildren(oldVNode, newVNode, container);
|
|
784
|
-
return;
|
|
785
|
-
}
|
|
786
|
-
const element = newVNode.dom = oldVNode.dom;
|
|
787
|
-
const oldProps = oldVNode.props || {};
|
|
788
|
-
const newProps = newVNode.props || {};
|
|
789
|
-
for (const key in oldProps) if (!(key in newProps) && key !== "children" && key !== "key" && key !== "ref") hostPatchProp(element, key, oldProps[key], null);
|
|
790
|
-
for (const key in newProps) {
|
|
791
|
-
const oldValue = oldProps[key];
|
|
792
|
-
const newValue = newProps[key];
|
|
793
|
-
if (key !== "children" && key !== "key" && key !== "ref" && oldValue !== newValue) hostPatchProp(element, key, oldValue, newValue);
|
|
794
|
-
}
|
|
795
|
-
patchChildren(oldVNode, newVNode, element);
|
|
796
|
-
}
|
|
797
|
-
function patchChildren(oldVNode, newVNode, container) {
|
|
798
|
-
const oldChildren = oldVNode.children;
|
|
799
|
-
const newChildren = newVNode.children;
|
|
800
|
-
newChildren.forEach((c) => c.parent = newVNode);
|
|
801
|
-
reconcileChildrenArray(container, oldChildren, newChildren);
|
|
802
|
-
}
|
|
803
|
-
function reconcileChildrenArray(parent, oldChildren, newChildren) {
|
|
804
|
-
let oldStartIdx = 0;
|
|
805
|
-
let oldEndIdx = oldChildren.length - 1;
|
|
806
|
-
let oldStartVNode = oldChildren[0];
|
|
807
|
-
let oldEndVNode = oldChildren[oldEndIdx];
|
|
808
|
-
let newStartIdx = 0;
|
|
809
|
-
let newEndIdx = newChildren.length - 1;
|
|
810
|
-
let newStartVNode = newChildren[0];
|
|
811
|
-
let newEndVNode = newChildren[newEndIdx];
|
|
812
|
-
let oldKeyToIdx;
|
|
813
|
-
while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) if (oldStartVNode == null) oldStartVNode = oldChildren[++oldStartIdx];
|
|
814
|
-
else if (oldEndVNode == null) oldEndVNode = oldChildren[--oldEndIdx];
|
|
815
|
-
else if (isSameVNode(oldStartVNode, newStartVNode)) {
|
|
816
|
-
patch(oldStartVNode, newStartVNode, parent);
|
|
817
|
-
oldStartVNode = oldChildren[++oldStartIdx];
|
|
818
|
-
newStartVNode = newChildren[++newStartIdx];
|
|
819
|
-
} else if (isSameVNode(oldEndVNode, newEndVNode)) {
|
|
820
|
-
patch(oldEndVNode, newEndVNode, parent);
|
|
821
|
-
oldEndVNode = oldChildren[--oldEndIdx];
|
|
822
|
-
newEndVNode = newChildren[--newEndIdx];
|
|
823
|
-
} else if (isSameVNode(oldStartVNode, newEndVNode)) {
|
|
824
|
-
patch(oldStartVNode, newEndVNode, parent);
|
|
825
|
-
const nodeToMove = oldStartVNode.dom;
|
|
826
|
-
const anchor = hostNextSibling(oldEndVNode.dom);
|
|
827
|
-
if (nodeToMove) hostInsert(nodeToMove, parent, anchor);
|
|
828
|
-
oldStartVNode = oldChildren[++oldStartIdx];
|
|
829
|
-
newEndVNode = newChildren[--newEndIdx];
|
|
830
|
-
} else if (isSameVNode(oldEndVNode, newStartVNode)) {
|
|
831
|
-
patch(oldEndVNode, newStartVNode, parent);
|
|
832
|
-
const nodeToMove = oldEndVNode.dom;
|
|
833
|
-
const anchor = oldStartVNode.dom;
|
|
834
|
-
if (nodeToMove) hostInsert(nodeToMove, parent, anchor);
|
|
835
|
-
oldEndVNode = oldChildren[--oldEndIdx];
|
|
836
|
-
newStartVNode = newChildren[++newStartIdx];
|
|
837
|
-
} else {
|
|
838
|
-
if (!oldKeyToIdx) oldKeyToIdx = createKeyToKeyIndexMap(oldChildren, oldStartIdx, oldEndIdx);
|
|
839
|
-
const idxInOld = newStartVNode.key != null ? oldKeyToIdx.get(String(newStartVNode.key)) : findIndexInOld(oldChildren, newStartVNode, oldStartIdx, oldEndIdx);
|
|
840
|
-
if (idxInOld != null) {
|
|
841
|
-
const vnodeToMove = oldChildren[idxInOld];
|
|
842
|
-
patch(vnodeToMove, newStartVNode, parent);
|
|
843
|
-
oldChildren[idxInOld] = void 0;
|
|
844
|
-
if (vnodeToMove.dom && oldStartVNode.dom) hostInsert(vnodeToMove.dom, parent, oldStartVNode.dom);
|
|
845
|
-
} else mount(newStartVNode, parent, oldStartVNode.dom);
|
|
846
|
-
newStartVNode = newChildren[++newStartIdx];
|
|
847
|
-
}
|
|
848
|
-
if (oldStartIdx > oldEndIdx) {
|
|
849
|
-
if (newStartIdx <= newEndIdx) {
|
|
850
|
-
const anchor = newChildren[newEndIdx + 1] == null ? null : newChildren[newEndIdx + 1].dom;
|
|
851
|
-
for (let i = newStartIdx; i <= newEndIdx; i++) mount(newChildren[i], parent, anchor);
|
|
852
|
-
}
|
|
853
|
-
} else if (newStartIdx > newEndIdx) {
|
|
854
|
-
for (let i = oldStartIdx; i <= oldEndIdx; i++) if (oldChildren[i]) unmount(oldChildren[i], parent);
|
|
855
|
-
}
|
|
856
|
-
}
|
|
857
|
-
function isSameVNode(n1, n2) {
|
|
858
|
-
const k1 = n1.key == null ? null : n1.key;
|
|
859
|
-
const k2 = n2.key == null ? null : n2.key;
|
|
860
|
-
if (n1.type !== n2.type) return false;
|
|
861
|
-
if (k1 === k2) return true;
|
|
862
|
-
return String(k1) === String(k2);
|
|
863
|
-
}
|
|
864
|
-
function createKeyToKeyIndexMap(children, beginIdx, endIdx) {
|
|
865
|
-
const map = /* @__PURE__ */ new Map();
|
|
866
|
-
for (let i = beginIdx; i <= endIdx; i++) {
|
|
867
|
-
const key = children[i]?.key;
|
|
868
|
-
if (key != null) map.set(String(key), i);
|
|
869
|
-
}
|
|
870
|
-
return map;
|
|
871
|
-
}
|
|
872
|
-
function findIndexInOld(children, newChild, beginIdx, endIdx) {
|
|
873
|
-
for (let i = beginIdx; i <= endIdx; i++) if (children[i] && isSameVNode(children[i], newChild)) return i;
|
|
874
|
-
return null;
|
|
875
|
-
}
|
|
876
|
-
function mountComponent(vnode, container, before, setup) {
|
|
877
|
-
const anchor = hostCreateComment("");
|
|
878
|
-
vnode.dom = anchor;
|
|
879
|
-
anchor.__vnode = vnode;
|
|
880
|
-
hostInsert(anchor, container, before);
|
|
881
|
-
let exposed = null;
|
|
882
|
-
let exposeCalled = false;
|
|
883
|
-
const { children, slots: slotsFromProps, ...propsData } = vnode.props || {};
|
|
884
|
-
const reactiveProps = signal(propsData);
|
|
885
|
-
const internalVNode = vnode;
|
|
886
|
-
internalVNode._componentProps = reactiveProps;
|
|
887
|
-
const slots = createSlots(children, slotsFromProps);
|
|
888
|
-
internalVNode._slots = slots;
|
|
889
|
-
const mountHooks = [];
|
|
890
|
-
const cleanupHooks = [];
|
|
891
|
-
const parentInstance = getCurrentInstance();
|
|
892
|
-
const componentName = vnode.type.__name;
|
|
893
|
-
const ctx = {
|
|
894
|
-
el: container,
|
|
895
|
-
signal,
|
|
896
|
-
props: createPropsAccessor(reactiveProps),
|
|
897
|
-
slots,
|
|
898
|
-
emit: (event, ...args) => {
|
|
899
|
-
const handler = reactiveProps[`on${event[0].toUpperCase() + event.slice(1)}`];
|
|
900
|
-
if (handler && typeof handler === "function") handler(...args);
|
|
901
|
-
},
|
|
902
|
-
parent: parentInstance,
|
|
903
|
-
onMount: (fn) => {
|
|
904
|
-
mountHooks.push(fn);
|
|
905
|
-
},
|
|
906
|
-
onCleanup: (fn) => {
|
|
907
|
-
cleanupHooks.push(fn);
|
|
908
|
-
},
|
|
909
|
-
expose: (exposedValue) => {
|
|
910
|
-
exposed = exposedValue;
|
|
911
|
-
exposeCalled = true;
|
|
912
|
-
},
|
|
913
|
-
renderFn: null,
|
|
914
|
-
update: () => {}
|
|
915
|
-
};
|
|
916
|
-
applyContextExtensions(ctx);
|
|
917
|
-
ctx.__name = componentName;
|
|
918
|
-
if (currentAppContext) ctx._appContext = currentAppContext;
|
|
919
|
-
const componentInstance = {
|
|
920
|
-
name: componentName,
|
|
921
|
-
ctx,
|
|
922
|
-
vnode
|
|
923
|
-
};
|
|
924
|
-
const prev = setCurrentInstance(ctx);
|
|
925
|
-
let renderFn;
|
|
926
|
-
try {
|
|
927
|
-
const setupResult = setup(ctx);
|
|
928
|
-
if (setupResult && typeof setupResult.then === "function") throw new Error(`Async setup in component "${componentName}" is only supported during SSR. On the client, use pre-loaded data from hydration or fetch in onMount.`);
|
|
929
|
-
renderFn = setupResult;
|
|
930
|
-
notifyComponentCreated(currentAppContext, componentInstance);
|
|
931
|
-
} catch (err) {
|
|
932
|
-
if (!handleComponentError(currentAppContext, err, componentInstance, "setup")) throw err;
|
|
933
|
-
} finally {
|
|
934
|
-
setCurrentInstance(prev);
|
|
935
|
-
}
|
|
936
|
-
if (vnode.props?.ref) {
|
|
937
|
-
const refValue = exposeCalled ? exposed : null;
|
|
938
|
-
if (typeof vnode.props.ref === "function") vnode.props.ref(refValue);
|
|
939
|
-
else if (vnode.props.ref && typeof vnode.props.ref === "object") vnode.props.ref.current = refValue;
|
|
940
|
-
}
|
|
941
|
-
if (renderFn) {
|
|
942
|
-
ctx.renderFn = renderFn;
|
|
943
|
-
const componentEffect = effect(() => {
|
|
944
|
-
const prevInstance = setCurrentInstance(ctx);
|
|
945
|
-
try {
|
|
946
|
-
const subTreeResult = ctx.renderFn();
|
|
947
|
-
if (subTreeResult == null) return;
|
|
948
|
-
const subTree = normalizeSubTree(subTreeResult);
|
|
949
|
-
const prevSubTree = internalVNode._subTree;
|
|
950
|
-
if (prevSubTree) {
|
|
951
|
-
patch(prevSubTree, subTree, container);
|
|
952
|
-
notifyComponentUpdated(currentAppContext, componentInstance);
|
|
953
|
-
} else mount(subTree, container, anchor);
|
|
954
|
-
internalVNode._subTree = subTree;
|
|
955
|
-
} catch (err) {
|
|
956
|
-
if (!handleComponentError(currentAppContext, err, componentInstance, "render")) throw err;
|
|
957
|
-
} finally {
|
|
958
|
-
setCurrentInstance(prevInstance);
|
|
959
|
-
}
|
|
960
|
-
});
|
|
961
|
-
internalVNode._effect = componentEffect;
|
|
962
|
-
ctx.update = () => {
|
|
963
|
-
componentEffect();
|
|
964
|
-
};
|
|
965
|
-
}
|
|
966
|
-
const mountCtx = { el: container };
|
|
967
|
-
mountHooks.forEach((hook) => hook(mountCtx));
|
|
968
|
-
notifyComponentMounted(currentAppContext, componentInstance);
|
|
969
|
-
vnode.cleanup = () => {
|
|
970
|
-
notifyComponentUnmounted(currentAppContext, componentInstance);
|
|
971
|
-
cleanupHooks.forEach((hook) => hook(mountCtx));
|
|
972
|
-
};
|
|
973
|
-
}
|
|
974
|
-
return {
|
|
975
|
-
render: render$1,
|
|
976
|
-
patch,
|
|
977
|
-
mount,
|
|
978
|
-
unmount,
|
|
979
|
-
mountComponent,
|
|
980
|
-
createApp: (rootComponent) => {
|
|
981
|
-
return { mount(selectorOrContainer) {
|
|
982
|
-
let container = null;
|
|
983
|
-
if (typeof selectorOrContainer === "string") {
|
|
984
|
-
if (options.querySelector) container = options.querySelector(selectorOrContainer);
|
|
985
|
-
} else container = selectorOrContainer;
|
|
986
|
-
if (!container) {
|
|
987
|
-
console.warn(`Container not found: ${selectorOrContainer}`);
|
|
988
|
-
return;
|
|
989
|
-
}
|
|
990
|
-
render$1(rootComponent, container);
|
|
991
|
-
} };
|
|
992
|
-
}
|
|
993
|
-
};
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
//#endregion
|
|
997
|
-
//#region src/focus.ts
|
|
998
|
-
const focusableIds = /* @__PURE__ */ new Set();
|
|
999
|
-
const focusState = signal({ activeId: null });
|
|
1
|
+
import { component as component$1, createRenderer, onMounted, onUnmounted, setDefaultMount, signal } from "@sigx/runtime-core";
|
|
2
|
+
import { signal as signal$1 } from "@sigx/reactivity";
|
|
3
|
+
import { jsx, jsxs } from "@sigx/runtime-core/jsx-runtime";
|
|
4
|
+
var focusableIds = /* @__PURE__ */ new Set();
|
|
5
|
+
const focusState = signal$1({ activeId: null });
|
|
1000
6
|
function registerFocusable(id) {
|
|
1001
7
|
focusableIds.add(id);
|
|
1002
8
|
if (focusState.activeId === null) focusState.activeId = id;
|
|
@@ -1021,9 +27,6 @@ function focusPrev() {
|
|
|
1021
27
|
const ids = Array.from(focusableIds);
|
|
1022
28
|
focusState.activeId = ids[((focusState.activeId ? ids.indexOf(focusState.activeId) : -1) - 1 + ids.length) % ids.length];
|
|
1023
29
|
}
|
|
1024
|
-
|
|
1025
|
-
//#endregion
|
|
1026
|
-
//#region src/utils.ts
|
|
1027
30
|
function getColorCode(color) {
|
|
1028
31
|
switch (color) {
|
|
1029
32
|
case "red": return "\x1B[31m";
|
|
@@ -1051,298 +54,48 @@ function getBackgroundColorCode(color) {
|
|
|
1051
54
|
function stripAnsi(str) {
|
|
1052
55
|
return str.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "");
|
|
1053
56
|
}
|
|
1054
|
-
|
|
1055
|
-
//#endregion
|
|
1056
|
-
//#region ../runtime-core/dist/index.js
|
|
1057
|
-
let platformSyncProcessor = null;
|
|
1058
|
-
/**
|
|
1059
|
-
* Get the current platform sync processor (for internal use).
|
|
1060
|
-
*/
|
|
1061
|
-
function getPlatformSyncProcessor() {
|
|
1062
|
-
return platformSyncProcessor;
|
|
1063
|
-
}
|
|
1064
|
-
const plugins = [];
|
|
1065
|
-
/**
|
|
1066
|
-
* Get all registered plugins (internal use)
|
|
1067
|
-
*/
|
|
1068
|
-
function getComponentPlugins() {
|
|
1069
|
-
return plugins;
|
|
1070
|
-
}
|
|
1071
|
-
const componentRegistry = /* @__PURE__ */ new Map();
|
|
1072
|
-
/**
|
|
1073
|
-
* Define a component. Returns a JSX factory function.
|
|
1074
|
-
*
|
|
1075
|
-
* @param setup - Setup function that receives context and returns a render function
|
|
1076
|
-
* @param options - Optional configuration (e.g., name for DevTools)
|
|
1077
|
-
*
|
|
1078
|
-
* @example
|
|
1079
|
-
* ```tsx
|
|
1080
|
-
* type CardProps = DefineProp<"title", string> & DefineSlot<"header">;
|
|
1081
|
-
*
|
|
1082
|
-
* export const Card = defineComponent<CardProps>((ctx) => {
|
|
1083
|
-
* const { title } = ctx.props;
|
|
1084
|
-
* const { slots } = ctx;
|
|
1085
|
-
*
|
|
1086
|
-
* return () => (
|
|
1087
|
-
* <div class="card">
|
|
1088
|
-
* {slots.header?.() ?? <h2>{title}</h2>}
|
|
1089
|
-
* {slots.default()}
|
|
1090
|
-
* </div>
|
|
1091
|
-
* );
|
|
1092
|
-
* });
|
|
1093
|
-
* ```
|
|
1094
|
-
*/
|
|
1095
|
-
function defineComponent$1(setup, options) {
|
|
1096
|
-
const factory = function(props) {
|
|
1097
|
-
return {
|
|
1098
|
-
type: factory,
|
|
1099
|
-
props: props || {},
|
|
1100
|
-
key: props?.key || null,
|
|
1101
|
-
children: [],
|
|
1102
|
-
dom: null
|
|
1103
|
-
};
|
|
1104
|
-
};
|
|
1105
|
-
factory.__setup = setup;
|
|
1106
|
-
factory.__name = options?.name;
|
|
1107
|
-
factory.__props = null;
|
|
1108
|
-
factory.__events = null;
|
|
1109
|
-
factory.__ref = null;
|
|
1110
|
-
factory.__slots = null;
|
|
1111
|
-
componentRegistry.set(factory, {
|
|
1112
|
-
name: options?.name,
|
|
1113
|
-
setup
|
|
1114
|
-
});
|
|
1115
|
-
getComponentPlugins().forEach((p) => p.onDefine?.(options?.name, factory, setup));
|
|
1116
|
-
return factory;
|
|
1117
|
-
}
|
|
1118
|
-
const Fragment = Symbol.for("sigx.Fragment");
|
|
1119
|
-
const Text = Symbol.for("sigx.Text");
|
|
1120
|
-
function normalizeChildren(children) {
|
|
1121
|
-
if (children == null || children === false || children === true) return [];
|
|
1122
|
-
if (Array.isArray(children)) return children.flatMap((c) => normalizeChildren(c));
|
|
1123
|
-
if (typeof children === "string" || typeof children === "number") return [{
|
|
1124
|
-
type: Text,
|
|
1125
|
-
props: {},
|
|
1126
|
-
key: null,
|
|
1127
|
-
children: [],
|
|
1128
|
-
dom: null,
|
|
1129
|
-
text: children
|
|
1130
|
-
}];
|
|
1131
|
-
if (children.type) return [children];
|
|
1132
|
-
return [];
|
|
1133
|
-
}
|
|
1134
|
-
/**
|
|
1135
|
-
* Check if a type is a sigx component (has __setup)
|
|
1136
|
-
*/
|
|
1137
|
-
function isComponent$1(type) {
|
|
1138
|
-
return typeof type === "function" && "__setup" in type;
|
|
1139
|
-
}
|
|
1140
|
-
/**
|
|
1141
|
-
* Create a JSX element - this is the core function called by TSX transpilation
|
|
1142
|
-
*/
|
|
1143
|
-
function jsx(type, props, key) {
|
|
1144
|
-
const processedProps = { ...props || {} };
|
|
1145
|
-
if (props) {
|
|
1146
|
-
for (const propKey in props) if (propKey === "sync") {
|
|
1147
|
-
let syncBinding = props[propKey];
|
|
1148
|
-
if (typeof syncBinding === "function") {
|
|
1149
|
-
const detected = detectAccess(syncBinding);
|
|
1150
|
-
if (detected) syncBinding = detected;
|
|
1151
|
-
}
|
|
1152
|
-
if (Array.isArray(syncBinding) && syncBinding.length === 2) {
|
|
1153
|
-
const [stateObj, key$1] = syncBinding;
|
|
1154
|
-
let handled = false;
|
|
1155
|
-
const platformProcessor = getPlatformSyncProcessor();
|
|
1156
|
-
if (typeof type === "string" && platformProcessor) handled = platformProcessor(type, processedProps, [stateObj, key$1], props);
|
|
1157
|
-
if (!handled) {
|
|
1158
|
-
processedProps.value = stateObj[key$1];
|
|
1159
|
-
const existingHandler = processedProps["onUpdate:value"];
|
|
1160
|
-
processedProps["onUpdate:value"] = (v) => {
|
|
1161
|
-
stateObj[key$1] = v;
|
|
1162
|
-
if (existingHandler) existingHandler(v);
|
|
1163
|
-
};
|
|
1164
|
-
}
|
|
1165
|
-
delete processedProps.sync;
|
|
1166
|
-
}
|
|
1167
|
-
} else if (propKey.startsWith("sync:")) {
|
|
1168
|
-
const syncBinding = props[propKey];
|
|
1169
|
-
if (Array.isArray(syncBinding) && syncBinding.length === 2) {
|
|
1170
|
-
const [stateObj, key$1] = syncBinding;
|
|
1171
|
-
const name = propKey.slice(5);
|
|
1172
|
-
processedProps[name] = stateObj[key$1];
|
|
1173
|
-
const eventName = `onUpdate:${name}`;
|
|
1174
|
-
const existingHandler = processedProps[eventName];
|
|
1175
|
-
processedProps[eventName] = (v) => {
|
|
1176
|
-
stateObj[key$1] = v;
|
|
1177
|
-
if (existingHandler) existingHandler(v);
|
|
1178
|
-
};
|
|
1179
|
-
delete processedProps[propKey];
|
|
1180
|
-
}
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
if (isComponent$1(type)) {
|
|
1184
|
-
const { children: children$1, ...rest$1 } = processedProps;
|
|
1185
|
-
return {
|
|
1186
|
-
type,
|
|
1187
|
-
props: {
|
|
1188
|
-
...rest$1,
|
|
1189
|
-
children: children$1
|
|
1190
|
-
},
|
|
1191
|
-
key: key || rest$1.key || null,
|
|
1192
|
-
children: [],
|
|
1193
|
-
dom: null
|
|
1194
|
-
};
|
|
1195
|
-
}
|
|
1196
|
-
if (typeof type === "function" && type !== Fragment) return type(processedProps);
|
|
1197
|
-
const { children, ...rest } = processedProps;
|
|
1198
|
-
return {
|
|
1199
|
-
type,
|
|
1200
|
-
props: rest,
|
|
1201
|
-
key: key || rest.key || null,
|
|
1202
|
-
children: normalizeChildren(children),
|
|
1203
|
-
dom: null
|
|
1204
|
-
};
|
|
1205
|
-
}
|
|
1206
|
-
/**
|
|
1207
|
-
* JSX Factory for fragments
|
|
1208
|
-
*/
|
|
1209
|
-
function jsxs(type, props, key) {
|
|
1210
|
-
return jsx(type, props, key);
|
|
1211
|
-
}
|
|
1212
|
-
/**
|
|
1213
|
-
* Lazy loading utilities for sigx components.
|
|
1214
|
-
*
|
|
1215
|
-
* Provides runtime-only lazy loading with no build dependencies.
|
|
1216
|
-
* Works with any bundler that supports dynamic import().
|
|
1217
|
-
*/
|
|
1218
|
-
let currentSuspenseBoundary = null;
|
|
1219
|
-
/**
|
|
1220
|
-
* Register a promise with the current Suspense boundary
|
|
1221
|
-
* @internal
|
|
1222
|
-
*/
|
|
1223
|
-
function registerPendingPromise(promise) {
|
|
1224
|
-
const boundary = currentSuspenseBoundary;
|
|
1225
|
-
if (boundary) {
|
|
1226
|
-
boundary.pending.add(promise);
|
|
1227
|
-
promise.finally(() => {
|
|
1228
|
-
boundary.pending.delete(promise);
|
|
1229
|
-
if (boundary.pending.size === 0) boundary.onResolve();
|
|
1230
|
-
});
|
|
1231
|
-
return true;
|
|
1232
|
-
}
|
|
1233
|
-
return false;
|
|
1234
|
-
}
|
|
1235
|
-
/**
|
|
1236
|
-
* Suspense boundary component for handling async loading states.
|
|
1237
|
-
*
|
|
1238
|
-
* Wraps lazy-loaded components and shows a fallback while they load.
|
|
1239
|
-
*
|
|
1240
|
-
* @example
|
|
1241
|
-
* ```tsx
|
|
1242
|
-
* import { lazy, Suspense } from 'sigx';
|
|
1243
|
-
*
|
|
1244
|
-
* const LazyDashboard = lazy(() => import('./Dashboard'));
|
|
1245
|
-
*
|
|
1246
|
-
* // Basic usage
|
|
1247
|
-
* <Suspense fallback={<div>Loading...</div>}>
|
|
1248
|
-
* <LazyDashboard />
|
|
1249
|
-
* </Suspense>
|
|
1250
|
-
*
|
|
1251
|
-
* // With spinner component
|
|
1252
|
-
* <Suspense fallback={<Spinner size="large" />}>
|
|
1253
|
-
* <LazyDashboard />
|
|
1254
|
-
* <LazyCharts />
|
|
1255
|
-
* </Suspense>
|
|
1256
|
-
* ```
|
|
1257
|
-
*/
|
|
1258
|
-
const Suspense = defineComponent$1((ctx) => {
|
|
1259
|
-
const { props, slots } = ctx;
|
|
1260
|
-
const state = ctx.signal({
|
|
1261
|
-
isReady: false,
|
|
1262
|
-
pendingCount: 0
|
|
1263
|
-
});
|
|
1264
|
-
const boundary = {
|
|
1265
|
-
pending: /* @__PURE__ */ new Set(),
|
|
1266
|
-
onResolve: () => {
|
|
1267
|
-
state.pendingCount = boundary.pending.size;
|
|
1268
|
-
if (boundary.pending.size === 0) state.isReady = true;
|
|
1269
|
-
}
|
|
1270
|
-
};
|
|
1271
|
-
ctx.onMount(() => {
|
|
1272
|
-
if (boundary.pending.size === 0) state.isReady = true;
|
|
1273
|
-
});
|
|
1274
|
-
return () => {
|
|
1275
|
-
state.isReady;
|
|
1276
|
-
state.pendingCount;
|
|
1277
|
-
const prevBoundary = currentSuspenseBoundary;
|
|
1278
|
-
currentSuspenseBoundary = boundary;
|
|
1279
|
-
try {
|
|
1280
|
-
const children = slots.default();
|
|
1281
|
-
if (boundary.pending.size > 0) {
|
|
1282
|
-
const fallback = props.fallback;
|
|
1283
|
-
if (typeof fallback === "function") return fallback();
|
|
1284
|
-
return fallback ?? null;
|
|
1285
|
-
}
|
|
1286
|
-
if (Array.isArray(children)) {
|
|
1287
|
-
const filtered = children.filter((c) => c != null && c !== false && c !== true);
|
|
1288
|
-
if (filtered.length === 0) return null;
|
|
1289
|
-
if (filtered.length === 1) return filtered[0];
|
|
1290
|
-
return filtered;
|
|
1291
|
-
}
|
|
1292
|
-
return children;
|
|
1293
|
-
} catch (err) {
|
|
1294
|
-
if (err instanceof Promise) {
|
|
1295
|
-
registerPendingPromise(err);
|
|
1296
|
-
const fallback = props.fallback;
|
|
1297
|
-
if (typeof fallback === "function") return fallback();
|
|
1298
|
-
return fallback ?? null;
|
|
1299
|
-
}
|
|
1300
|
-
throw err;
|
|
1301
|
-
} finally {
|
|
1302
|
-
currentSuspenseBoundary = prevBoundary;
|
|
1303
|
-
}
|
|
1304
|
-
};
|
|
1305
|
-
}, { name: "Suspense" });
|
|
1306
|
-
|
|
1307
|
-
//#endregion
|
|
1308
|
-
//#region src/components/Input.tsx
|
|
1309
|
-
/** @jsxImportSource @sigx/runtime-core */
|
|
1310
|
-
const Input = defineComponent(({ props, emit }) => {
|
|
57
|
+
const Input = component$1(({ props, emit }) => {
|
|
1311
58
|
const id = Math.random().toString(36).slice(2);
|
|
59
|
+
let isReady = false;
|
|
1312
60
|
const isFocused = () => focusState.activeId === id;
|
|
61
|
+
const getValue = () => props.model?.value || "";
|
|
1313
62
|
const handleKey = (key) => {
|
|
1314
63
|
if (!isFocused()) return;
|
|
64
|
+
if (!isReady) return;
|
|
1315
65
|
if (key === "\r") {
|
|
1316
|
-
emit("submit",
|
|
66
|
+
emit("submit", getValue());
|
|
1317
67
|
return;
|
|
1318
68
|
}
|
|
1319
69
|
if (key === "\n") return;
|
|
1320
70
|
if (key === "" || key === "\b") {
|
|
1321
|
-
const val =
|
|
71
|
+
const val = getValue();
|
|
1322
72
|
if (val.length > 0) {
|
|
1323
|
-
const newValue
|
|
1324
|
-
|
|
1325
|
-
emit("input", newValue
|
|
73
|
+
const newValue = val.slice(0, -1);
|
|
74
|
+
if (props.model) props.model.value = newValue;
|
|
75
|
+
emit("input", newValue);
|
|
1326
76
|
}
|
|
1327
77
|
return;
|
|
1328
78
|
}
|
|
1329
79
|
if (key.length > 1) return;
|
|
1330
|
-
const newValue = (
|
|
1331
|
-
|
|
80
|
+
const newValue = getValue() + key;
|
|
81
|
+
if (props.model) props.model.value = newValue;
|
|
1332
82
|
emit("input", newValue);
|
|
1333
83
|
};
|
|
1334
84
|
let keyCleanup = null;
|
|
1335
|
-
|
|
85
|
+
onMounted(() => {
|
|
1336
86
|
registerFocusable(id);
|
|
1337
87
|
if (props.autofocus) focus(id);
|
|
1338
88
|
keyCleanup = onKey(handleKey);
|
|
89
|
+
setTimeout(() => {
|
|
90
|
+
isReady = true;
|
|
91
|
+
}, 50);
|
|
1339
92
|
});
|
|
1340
|
-
|
|
93
|
+
onUnmounted(() => {
|
|
1341
94
|
if (keyCleanup) keyCleanup();
|
|
1342
95
|
unregisterFocusable(id);
|
|
1343
96
|
});
|
|
1344
97
|
return () => {
|
|
1345
|
-
const val = (
|
|
98
|
+
const val = getValue().replace(/[\r\n]+/g, " ");
|
|
1346
99
|
const placeholder = (props.placeholder || "").replace(/[\r\n]+/g, " ");
|
|
1347
100
|
const showCursor = isFocused();
|
|
1348
101
|
return /* @__PURE__ */ jsxs("box", {
|
|
@@ -1356,11 +109,7 @@ const Input = defineComponent(({ props, emit }) => {
|
|
|
1356
109
|
});
|
|
1357
110
|
};
|
|
1358
111
|
}, { name: "Input" });
|
|
1359
|
-
|
|
1360
|
-
//#endregion
|
|
1361
|
-
//#region src/components/ProgressBar.tsx
|
|
1362
|
-
/** @jsxImportSource @sigx/runtime-core */
|
|
1363
|
-
const ProgressBar = defineComponent(({ props }) => {
|
|
112
|
+
const ProgressBar = component$1(({ props }) => {
|
|
1364
113
|
return () => {
|
|
1365
114
|
const value = props.value || 0;
|
|
1366
115
|
const max = props.max || 100;
|
|
@@ -1376,11 +125,7 @@ const ProgressBar = defineComponent(({ props }) => {
|
|
|
1376
125
|
return /* @__PURE__ */ jsx("box", { children: /* @__PURE__ */ jsx("text", { children: colorCode + barChar.repeat(filledLen) + emptyChar.repeat(emptyLen) + reset + ` ${Math.round(percentage * 100)}%` }) });
|
|
1377
126
|
};
|
|
1378
127
|
}, { name: "ProgressBar" });
|
|
1379
|
-
|
|
1380
|
-
//#endregion
|
|
1381
|
-
//#region src/components/Button.tsx
|
|
1382
|
-
/** @jsxImportSource @sigx/runtime-core */
|
|
1383
|
-
const Button = defineComponent(({ props, emit }) => {
|
|
128
|
+
const Button = component$1(({ props, emit }) => {
|
|
1384
129
|
const id = Math.random().toString(36).slice(2);
|
|
1385
130
|
const isFocused = () => focusState.activeId === id;
|
|
1386
131
|
const pressed = signal({ value: false });
|
|
@@ -1398,11 +143,11 @@ const Button = defineComponent(({ props, emit }) => {
|
|
|
1398
143
|
};
|
|
1399
144
|
let keyCleanup = null;
|
|
1400
145
|
let pressTimer = null;
|
|
1401
|
-
|
|
146
|
+
onMounted(() => {
|
|
1402
147
|
registerFocusable(id);
|
|
1403
148
|
keyCleanup = onKey(handleKey);
|
|
1404
149
|
});
|
|
1405
|
-
|
|
150
|
+
onUnmounted(() => {
|
|
1406
151
|
if (keyCleanup) keyCleanup();
|
|
1407
152
|
unregisterFocusable(id);
|
|
1408
153
|
if (pressTimer) clearTimeout(pressTimer);
|
|
@@ -1423,30 +168,26 @@ const Button = defineComponent(({ props, emit }) => {
|
|
|
1423
168
|
});
|
|
1424
169
|
};
|
|
1425
170
|
}, { name: "Button" });
|
|
1426
|
-
|
|
1427
|
-
//#endregion
|
|
1428
|
-
//#region src/components/Checkbox.tsx
|
|
1429
|
-
/** @jsxImportSource @sigx/runtime-core */
|
|
1430
|
-
const Checkbox = defineComponent(({ props, emit }) => {
|
|
171
|
+
const Checkbox = component$1(({ props, emit }) => {
|
|
1431
172
|
const id = Math.random().toString(36).slice(2);
|
|
1432
173
|
const isFocused = () => focusState.activeId === id;
|
|
1433
|
-
const checked = () => !!props.value;
|
|
174
|
+
const checked = () => !!props.model?.value;
|
|
1434
175
|
const handleKey = (key) => {
|
|
1435
176
|
if (!isFocused()) return;
|
|
1436
177
|
if (props.disabled) return;
|
|
1437
178
|
if (key === "\r" || key === " ") {
|
|
1438
179
|
const next = !checked();
|
|
1439
|
-
|
|
180
|
+
if (props.model) props.model.value = next;
|
|
1440
181
|
emit("change", next);
|
|
1441
182
|
}
|
|
1442
183
|
};
|
|
1443
184
|
let keyCleanup = null;
|
|
1444
|
-
|
|
185
|
+
onMounted(() => {
|
|
1445
186
|
registerFocusable(id);
|
|
1446
187
|
if (props.autofocus) focus(id);
|
|
1447
188
|
keyCleanup = onKey(handleKey);
|
|
1448
189
|
});
|
|
1449
|
-
|
|
190
|
+
onUnmounted(() => {
|
|
1450
191
|
if (keyCleanup) keyCleanup();
|
|
1451
192
|
unregisterFocusable(id);
|
|
1452
193
|
});
|
|
@@ -1475,79 +216,80 @@ const Checkbox = defineComponent(({ props, emit }) => {
|
|
|
1475
216
|
] });
|
|
1476
217
|
};
|
|
1477
218
|
}, { name: "Checkbox" });
|
|
1478
|
-
|
|
1479
|
-
//#endregion
|
|
1480
|
-
//#region src/components/Select.tsx
|
|
1481
|
-
/** @jsxImportSource @sigx/runtime-core */
|
|
1482
|
-
const Select = defineComponent(({ props, emit }) => {
|
|
219
|
+
const Select = component$1(({ props, emit }) => {
|
|
1483
220
|
const id = Math.random().toString(36).slice(2);
|
|
221
|
+
let isReady = false;
|
|
1484
222
|
const isFocused = () => focusState.activeId === id;
|
|
1485
223
|
const getCurrentIndex = () => {
|
|
1486
|
-
const idx = (props.options || []).findIndex((o) => o.value === props.value);
|
|
224
|
+
const idx = (props.options || []).findIndex((o) => o.value === props.model?.value);
|
|
1487
225
|
return idx >= 0 ? idx : 0;
|
|
1488
226
|
};
|
|
1489
227
|
const handleKey = (key) => {
|
|
1490
228
|
if (!isFocused()) return;
|
|
229
|
+
if (!isReady) return;
|
|
1491
230
|
const options = props.options || [];
|
|
1492
231
|
if (options.length === 0) return;
|
|
1493
232
|
const currentIndex = getCurrentIndex();
|
|
1494
233
|
if (key === "\x1B[A" || key === "k") {
|
|
1495
234
|
const newValue = options[currentIndex > 0 ? currentIndex - 1 : options.length - 1].value;
|
|
1496
|
-
|
|
235
|
+
if (props.model) props.model.value = newValue;
|
|
1497
236
|
emit("change", newValue);
|
|
1498
237
|
return;
|
|
1499
238
|
}
|
|
1500
239
|
if (key === "\x1B[B" || key === "j") {
|
|
1501
240
|
const newValue = options[currentIndex < options.length - 1 ? currentIndex + 1 : 0].value;
|
|
1502
|
-
|
|
241
|
+
if (props.model) props.model.value = newValue;
|
|
1503
242
|
emit("change", newValue);
|
|
1504
243
|
return;
|
|
1505
244
|
}
|
|
1506
245
|
if (key === "\r") {
|
|
1507
|
-
emit("submit", props.value || options[0]?.value || "");
|
|
246
|
+
emit("submit", props.model?.value || options[0]?.value || "");
|
|
1508
247
|
return;
|
|
1509
248
|
}
|
|
1510
249
|
};
|
|
1511
250
|
let keyCleanup = null;
|
|
1512
|
-
|
|
251
|
+
onMounted(() => {
|
|
1513
252
|
registerFocusable(id);
|
|
1514
253
|
if (props.autofocus) focus(id);
|
|
1515
254
|
keyCleanup = onKey(handleKey);
|
|
255
|
+
setTimeout(() => {
|
|
256
|
+
isReady = true;
|
|
257
|
+
}, 50);
|
|
1516
258
|
});
|
|
1517
|
-
|
|
259
|
+
onUnmounted(() => {
|
|
1518
260
|
if (keyCleanup) keyCleanup();
|
|
1519
261
|
unregisterFocusable(id);
|
|
1520
262
|
});
|
|
1521
263
|
return () => {
|
|
1522
264
|
const options = props.options || [];
|
|
1523
265
|
const focused = isFocused();
|
|
1524
|
-
const currentValue = props.value || options[0]?.value || "";
|
|
266
|
+
const currentValue = props.model?.value || options[0]?.value || "";
|
|
1525
267
|
const label = props.label;
|
|
1526
|
-
|
|
268
|
+
const selectedOption = options.find((o) => o.value === currentValue);
|
|
269
|
+
const optionElements = options.map((option) => {
|
|
270
|
+
const isSelected = option.value === currentValue;
|
|
271
|
+
return /* @__PURE__ */ jsx("box", { children: /* @__PURE__ */ jsxs("text", {
|
|
272
|
+
color: isSelected ? "cyan" : "white",
|
|
273
|
+
children: [
|
|
274
|
+
isSelected ? "❯" : " ",
|
|
275
|
+
" ",
|
|
276
|
+
option.label
|
|
277
|
+
]
|
|
278
|
+
}) });
|
|
279
|
+
});
|
|
280
|
+
const descriptionElement = props.showDescription && selectedOption?.description ? /* @__PURE__ */ jsx("box", { children: /* @__PURE__ */ jsxs("text", {
|
|
281
|
+
color: "#666666",
|
|
282
|
+
children: [" ↳ ", selectedOption.description]
|
|
283
|
+
}) }) : null;
|
|
284
|
+
return /* @__PURE__ */ jsxs("box", { children: [/* @__PURE__ */ jsx("box", {
|
|
1527
285
|
border: "single",
|
|
1528
286
|
borderColor: focused ? "green" : "white",
|
|
1529
287
|
label,
|
|
1530
|
-
children:
|
|
1531
|
-
|
|
1532
|
-
return /* @__PURE__ */ jsxs("box", { children: [/* @__PURE__ */ jsxs("text", {
|
|
1533
|
-
color: isSelected ? "cyan" : "white",
|
|
1534
|
-
children: [
|
|
1535
|
-
isSelected ? "❯" : " ",
|
|
1536
|
-
" ",
|
|
1537
|
-
option.label
|
|
1538
|
-
]
|
|
1539
|
-
}), option.description && isSelected && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("br", {}), /* @__PURE__ */ jsxs("text", {
|
|
1540
|
-
color: "white",
|
|
1541
|
-
children: [" ", option.description]
|
|
1542
|
-
})] })] });
|
|
1543
|
-
})
|
|
1544
|
-
});
|
|
288
|
+
children: optionElements
|
|
289
|
+
}), descriptionElement] });
|
|
1545
290
|
};
|
|
1546
291
|
}, { name: "Select" });
|
|
1547
|
-
|
|
1548
|
-
//#endregion
|
|
1549
|
-
//#region src/index.ts
|
|
1550
|
-
const renderer = createRenderer({
|
|
292
|
+
const { render } = createRenderer({
|
|
1551
293
|
patchProp: (el, key, prev, next) => {
|
|
1552
294
|
el.props[key] = next;
|
|
1553
295
|
scheduleRender();
|
|
@@ -1618,9 +360,8 @@ const renderer = createRenderer({
|
|
|
1618
360
|
};
|
|
1619
361
|
}
|
|
1620
362
|
});
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
let isRendering = false;
|
|
363
|
+
var rootNode = null;
|
|
364
|
+
var isRendering = false;
|
|
1624
365
|
function scheduleRender() {
|
|
1625
366
|
if (isRendering) return;
|
|
1626
367
|
isRendering = true;
|
|
@@ -1636,10 +377,6 @@ function flushRender() {
|
|
|
1636
377
|
process.stdout.write(lines.join("\x1B[K\n") + "\x1B[K");
|
|
1637
378
|
process.stdout.write("\x1B[J");
|
|
1638
379
|
}
|
|
1639
|
-
/**
|
|
1640
|
-
* Check if a node has a box element as an immediate child.
|
|
1641
|
-
* This is used to determine if a component wrapper should be treated as a block element.
|
|
1642
|
-
*/
|
|
1643
380
|
function hasBoxChild(node) {
|
|
1644
381
|
for (const child of node.children) if (child.tag === "box") return true;
|
|
1645
382
|
return false;
|
|
@@ -1728,7 +465,7 @@ function getBorderChars(style) {
|
|
|
1728
465
|
v: "│"
|
|
1729
466
|
};
|
|
1730
467
|
}
|
|
1731
|
-
|
|
468
|
+
var keyHandlers = /* @__PURE__ */ new Set();
|
|
1732
469
|
function onKey(handler) {
|
|
1733
470
|
keyHandlers.add(handler);
|
|
1734
471
|
return () => keyHandlers.delete(handler);
|
|
@@ -1775,16 +512,7 @@ function renderTerminal(app, options = {}) {
|
|
|
1775
512
|
}
|
|
1776
513
|
} };
|
|
1777
514
|
}
|
|
1778
|
-
|
|
1779
|
-
/**
|
|
1780
|
-
* Helper function to mount the terminal for CLI apps.
|
|
1781
|
-
* Returns a mount target that can be passed to defineApp().mount().
|
|
1782
|
-
*
|
|
1783
|
-
* @example
|
|
1784
|
-
* ```tsx
|
|
1785
|
-
* defineApp(MyApp).mount(mountTerminal());
|
|
1786
|
-
* ```
|
|
1787
|
-
*/
|
|
515
|
+
var unmountFn = null;
|
|
1788
516
|
function mountTerminal(options = { clearConsole: true }) {
|
|
1789
517
|
return {
|
|
1790
518
|
mount: terminalMount,
|
|
@@ -1794,9 +522,6 @@ function mountTerminal(options = { clearConsole: true }) {
|
|
|
1794
522
|
}
|
|
1795
523
|
};
|
|
1796
524
|
}
|
|
1797
|
-
/**
|
|
1798
|
-
* Exit the terminal app cleanly, restoring terminal state.
|
|
1799
|
-
*/
|
|
1800
525
|
function exitTerminal() {
|
|
1801
526
|
if (unmountFn) {
|
|
1802
527
|
unmountFn();
|
|
@@ -1805,20 +530,6 @@ function exitTerminal() {
|
|
|
1805
530
|
process.stdout.write("\x1B[?25h");
|
|
1806
531
|
process.stdout.write("\x1B[2J\x1B[H");
|
|
1807
532
|
}
|
|
1808
|
-
/**
|
|
1809
|
-
* Mount function for Terminal environments.
|
|
1810
|
-
* Use this with defineApp().mount() to render to the terminal.
|
|
1811
|
-
*
|
|
1812
|
-
* @example
|
|
1813
|
-
* ```tsx
|
|
1814
|
-
* import { defineApp } from '@sigx/runtime-core';
|
|
1815
|
-
* import { terminalMount } from '@sigx/runtime-terminal';
|
|
1816
|
-
*
|
|
1817
|
-
* const app = defineApp(<Counter />);
|
|
1818
|
-
* app.use(loggingPlugin)
|
|
1819
|
-
* .mount({ clearConsole: true }, terminalMount);
|
|
1820
|
-
* ```
|
|
1821
|
-
*/
|
|
1822
533
|
const terminalMount = (component, options, appContext) => {
|
|
1823
534
|
rootNode = {
|
|
1824
535
|
type: "root",
|
|
@@ -1847,7 +558,6 @@ const terminalMount = (component, options, appContext) => {
|
|
|
1847
558
|
};
|
|
1848
559
|
};
|
|
1849
560
|
setDefaultMount(terminalMount);
|
|
561
|
+
export { Button, Checkbox, Input, ProgressBar, Select, exitTerminal, focus, focusNext, focusPrev, focusState, mountTerminal, onKey, registerFocusable, render, renderNodeToLines, renderTerminal, terminalMount, unregisterFocusable };
|
|
1850
562
|
|
|
1851
|
-
//#endregion
|
|
1852
|
-
export { Button, Checkbox, Input, ProgressBar, Select, createApp, exitTerminal, focus, focusNext, focusPrev, focusState, mountTerminal, onKey, registerFocusable, render, renderNodeToLines, renderTerminal, terminalMount, unregisterFocusable };
|
|
1853
563
|
//# sourceMappingURL=index.js.map
|