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