@sigx/terminal 0.1.5 → 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/dist/index.js CHANGED
@@ -1,7 +1,13 @@
1
- //#region ../reactivity/src/index.ts
1
+ const ComputedSymbol = Symbol("computed");
2
2
  let activeEffect = null;
3
- let batchDepth = 0;
4
- const pendingEffects = /* @__PURE__ */ new Set();
3
+ var batchDepth = 0;
4
+ var pendingEffects = /* @__PURE__ */ new Set();
5
+ function setActiveEffect(effect) {
6
+ activeEffect = effect;
7
+ }
8
+ function getActiveEffect() {
9
+ return activeEffect;
10
+ }
5
11
  function batch(fn) {
6
12
  batchDepth++;
7
13
  try {
@@ -11,10 +17,25 @@ function batch(fn) {
11
17
  if (batchDepth === 0) {
12
18
  const effects = Array.from(pendingEffects);
13
19
  pendingEffects.clear();
14
- for (const effect$1 of effects) effect$1();
20
+ for (const effect of effects) effect();
15
21
  }
16
22
  }
17
23
  }
24
+ function cleanup(effect) {
25
+ if (!effect.deps) return;
26
+ for (const dep of effect.deps) dep.delete(effect);
27
+ effect.deps.length = 0;
28
+ }
29
+ function track(depSet) {
30
+ if (!activeEffect) return;
31
+ depSet.add(activeEffect);
32
+ activeEffect.deps.push(depSet);
33
+ }
34
+ function trigger(depSet) {
35
+ const effects = Array.from(depSet);
36
+ for (const effect of effects) if (batchDepth > 0) pendingEffects.add(effect);
37
+ else effect();
38
+ }
18
39
  function runEffect(fn) {
19
40
  const effectFn = function() {
20
41
  cleanup(effectFn);
@@ -28,27 +49,228 @@ function runEffect(fn) {
28
49
  runner.stop = () => cleanup(effectFn);
29
50
  return runner;
30
51
  }
31
- function cleanup(effect$1) {
32
- if (!effect$1.deps) return;
33
- for (const dep of effect$1.deps) dep.delete(effect$1);
34
- effect$1.deps.length = 0;
52
+ function effect(fn) {
53
+ return runEffect(fn);
35
54
  }
36
- function track(depSet) {
37
- if (!activeEffect) return;
38
- depSet.add(activeEffect);
39
- activeEffect.deps.push(depSet);
55
+ function untrack(fn) {
56
+ const prev = activeEffect;
57
+ activeEffect = null;
58
+ try {
59
+ return fn();
60
+ } finally {
61
+ activeEffect = prev;
62
+ }
40
63
  }
41
- function trigger(depSet) {
42
- const effects = Array.from(depSet);
43
- for (const effect$1 of effects) if (batchDepth > 0) pendingEffects.add(effect$1);
44
- else effect$1();
64
+ function effectScope(detached) {
65
+ const effects = [];
66
+ let active = true;
67
+ return {
68
+ run(fn) {
69
+ if (!active) return void 0;
70
+ return fn();
71
+ },
72
+ stop() {
73
+ active = false;
74
+ effects.forEach((e) => e());
75
+ }
76
+ };
77
+ }
78
+ const ITERATE_KEY = Symbol("iterate");
79
+ const reactiveToRaw = /* @__PURE__ */ new WeakMap();
80
+ const rawToReactive = /* @__PURE__ */ new WeakMap();
81
+ function toRaw(observed) {
82
+ const raw = reactiveToRaw.get(observed);
83
+ return raw ? toRaw(raw) : observed;
84
+ }
85
+ function isReactive(value) {
86
+ return reactiveToRaw.has(value);
87
+ }
88
+ function isCollection(value) {
89
+ if (!value || typeof value !== "object") return false;
90
+ const ctor = value.constructor;
91
+ return ctor === Set || ctor === Map || ctor === WeakSet || ctor === WeakMap;
92
+ }
93
+ function isIterableCollection(value) {
94
+ if (!value || typeof value !== "object") return false;
95
+ const ctor = value.constructor;
96
+ return ctor === Set || ctor === Map;
97
+ }
98
+ function shouldNotProxy(value) {
99
+ if (!value || typeof value !== "object") return false;
100
+ const proto = Object.prototype.toString.call(value);
101
+ return [
102
+ "[object Date]",
103
+ "[object RegExp]",
104
+ "[object Error]",
105
+ "[object Promise]",
106
+ "[object ArrayBuffer]",
107
+ "[object DataView]",
108
+ "[object Int8Array]",
109
+ "[object Uint8Array]",
110
+ "[object Uint8ClampedArray]",
111
+ "[object Int16Array]",
112
+ "[object Uint16Array]",
113
+ "[object Int32Array]",
114
+ "[object Uint32Array]",
115
+ "[object Float32Array]",
116
+ "[object Float64Array]",
117
+ "[object BigInt64Array]",
118
+ "[object BigUint64Array]"
119
+ ].includes(proto);
120
+ }
121
+ function createCollectionInstrumentations(depsMap, getOrCreateDep) {
122
+ const instrumentations = {};
123
+ instrumentations.has = function(key) {
124
+ const target = toRaw(this);
125
+ const rawKey = toRaw(key);
126
+ track(getOrCreateDep(rawKey));
127
+ return target.has(rawKey);
128
+ };
129
+ instrumentations.get = function(key) {
130
+ const target = toRaw(this);
131
+ const rawKey = toRaw(key);
132
+ track(getOrCreateDep(rawKey));
133
+ const value = target.get(rawKey);
134
+ if (value && typeof value === "object") return rawToReactive.get(value) || value;
135
+ return value;
136
+ };
137
+ Object.defineProperty(instrumentations, "size", { get() {
138
+ const target = toRaw(this);
139
+ track(getOrCreateDep(ITERATE_KEY));
140
+ return target.size;
141
+ } });
142
+ instrumentations.forEach = function(callback, thisArg) {
143
+ const target = toRaw(this);
144
+ track(getOrCreateDep(ITERATE_KEY));
145
+ target.forEach((value, key) => {
146
+ const reactiveValue = value && typeof value === "object" ? rawToReactive.get(value) || value : value;
147
+ const reactiveKey = key && typeof key === "object" ? rawToReactive.get(key) || key : key;
148
+ callback.call(thisArg, reactiveValue, reactiveKey, this);
149
+ });
150
+ };
151
+ instrumentations.keys = function() {
152
+ const target = toRaw(this);
153
+ track(getOrCreateDep(ITERATE_KEY));
154
+ return createReactiveIterator(target.keys(), false);
155
+ };
156
+ instrumentations.values = function() {
157
+ const target = toRaw(this);
158
+ track(getOrCreateDep(ITERATE_KEY));
159
+ return createReactiveIterator(target.values(), true);
160
+ };
161
+ instrumentations.entries = function() {
162
+ const target = toRaw(this);
163
+ track(getOrCreateDep(ITERATE_KEY));
164
+ return createReactiveEntriesIterator(target.entries());
165
+ };
166
+ instrumentations[Symbol.iterator] = function() {
167
+ const target = toRaw(this);
168
+ track(getOrCreateDep(ITERATE_KEY));
169
+ if (target instanceof Set) return createReactiveIterator(target.values(), true);
170
+ else return createReactiveEntriesIterator(target.entries());
171
+ };
172
+ instrumentations.add = function(value) {
173
+ const target = toRaw(this);
174
+ const rawValue = toRaw(value);
175
+ const hadKey = target.has(rawValue);
176
+ target.add(rawValue);
177
+ if (!hadKey) {
178
+ const dep = depsMap.get(rawValue);
179
+ if (dep) trigger(dep);
180
+ const iterDep = depsMap.get(ITERATE_KEY);
181
+ if (iterDep) trigger(iterDep);
182
+ }
183
+ return this;
184
+ };
185
+ instrumentations.set = function(key, value) {
186
+ const target = toRaw(this);
187
+ const rawKey = toRaw(key);
188
+ const rawValue = toRaw(value);
189
+ const hadKey = target.has(rawKey);
190
+ const oldValue = target.get(rawKey);
191
+ target.set(rawKey, rawValue);
192
+ if (!hadKey) {
193
+ const iterDep = depsMap.get(ITERATE_KEY);
194
+ if (iterDep) trigger(iterDep);
195
+ }
196
+ if (!hadKey || !Object.is(oldValue, rawValue)) {
197
+ const dep = depsMap.get(rawKey);
198
+ if (dep) trigger(dep);
199
+ }
200
+ return this;
201
+ };
202
+ instrumentations.delete = function(key) {
203
+ const target = toRaw(this);
204
+ const rawKey = toRaw(key);
205
+ const hadKey = target.has(rawKey);
206
+ const result = target.delete(rawKey);
207
+ if (hadKey) {
208
+ const dep = depsMap.get(rawKey);
209
+ if (dep) trigger(dep);
210
+ const iterDep = depsMap.get(ITERATE_KEY);
211
+ if (iterDep) trigger(iterDep);
212
+ }
213
+ return result;
214
+ };
215
+ instrumentations.clear = function() {
216
+ const target = toRaw(this);
217
+ const hadItems = target.size > 0;
218
+ target.clear();
219
+ if (hadItems) for (const dep of depsMap.values()) trigger(dep);
220
+ };
221
+ return instrumentations;
222
+ }
223
+ function createReactiveIterator(innerIterator, wrapValues) {
224
+ return {
225
+ next() {
226
+ const { value, done } = innerIterator.next();
227
+ if (done) return {
228
+ value: void 0,
229
+ done: true
230
+ };
231
+ return {
232
+ value: wrapValues && value && typeof value === "object" ? rawToReactive.get(value) || value : value,
233
+ done: false
234
+ };
235
+ },
236
+ [Symbol.iterator]() {
237
+ return this;
238
+ }
239
+ };
240
+ }
241
+ function createReactiveEntriesIterator(innerIterator) {
242
+ return {
243
+ next() {
244
+ const { value, done } = innerIterator.next();
245
+ if (done) return {
246
+ value: void 0,
247
+ done: true
248
+ };
249
+ const [key, val] = value;
250
+ return {
251
+ value: [key && typeof key === "object" ? rawToReactive.get(key) || key : key, val && typeof val === "object" ? rawToReactive.get(val) || val : val],
252
+ done: false
253
+ };
254
+ },
255
+ [Symbol.iterator]() {
256
+ return this;
257
+ }
258
+ };
259
+ }
260
+ function isPrimitive(value) {
261
+ if (value === null || value === void 0) return true;
262
+ const type = typeof value;
263
+ return type === "string" || type === "number" || type === "boolean" || type === "symbol" || type === "bigint";
264
+ }
265
+ var accessObserver = null;
266
+ function getAccessObserver() {
267
+ return accessObserver;
45
268
  }
46
- let accessObserver = null;
47
269
  function detectAccess(selector) {
48
270
  let result = null;
49
271
  const prev = accessObserver;
50
272
  accessObserver = (target, key) => {
51
- result = [target, key];
273
+ if (result === null) result = [target, key];
52
274
  };
53
275
  try {
54
276
  selector();
@@ -57,19 +279,43 @@ function detectAccess(selector) {
57
279
  }
58
280
  return result;
59
281
  }
60
- function untrack(fn) {
61
- const prev = activeEffect;
62
- activeEffect = null;
63
- try {
64
- return fn();
65
- } finally {
66
- activeEffect = prev;
67
- }
68
- }
282
+ var arrayInstrumentations = {};
283
+ [
284
+ "push",
285
+ "pop",
286
+ "shift",
287
+ "unshift",
288
+ "splice",
289
+ "sort",
290
+ "reverse"
291
+ ].forEach((method) => {
292
+ arrayInstrumentations[method] = function(...args) {
293
+ let res;
294
+ batch(() => {
295
+ res = Array.prototype[method].apply(this, args);
296
+ });
297
+ return res;
298
+ };
299
+ });
69
300
  function signal(target) {
301
+ if (isPrimitive(target)) return signal({ value: target });
302
+ const objectTarget = target;
303
+ if (shouldNotProxy(objectTarget)) return objectTarget;
304
+ if (isReactive(objectTarget)) return objectTarget;
305
+ const existingProxy = rawToReactive.get(objectTarget);
306
+ if (existingProxy) return existingProxy;
70
307
  const depsMap = /* @__PURE__ */ new Map();
71
308
  const reactiveCache = /* @__PURE__ */ new WeakMap();
72
- return new Proxy(target, {
309
+ const getOrCreateDep = (key) => {
310
+ let dep = depsMap.get(key);
311
+ if (!dep) {
312
+ dep = /* @__PURE__ */ new Set();
313
+ depsMap.set(key, dep);
314
+ }
315
+ return dep;
316
+ };
317
+ const collectionInstrumentations = isCollection(objectTarget) ? createCollectionInstrumentations(depsMap, getOrCreateDep) : null;
318
+ const proxy = new Proxy(objectTarget, {
73
319
  get(obj, prop, receiver) {
74
320
  if (prop === "$set") return (newValue) => {
75
321
  batch(() => {
@@ -85,16 +331,22 @@ function signal(target) {
85
331
  }
86
332
  });
87
333
  };
334
+ if (collectionInstrumentations) {
335
+ if (prop === "size" && isIterableCollection(obj)) {
336
+ track(getOrCreateDep(ITERATE_KEY));
337
+ return obj.size;
338
+ }
339
+ if (prop in collectionInstrumentations) {
340
+ const instrumented = collectionInstrumentations[prop];
341
+ if (typeof instrumented === "function") return instrumented.bind(receiver);
342
+ return instrumented;
343
+ }
344
+ }
88
345
  if (Array.isArray(obj) && typeof prop === "string" && arrayInstrumentations.hasOwnProperty(prop)) return arrayInstrumentations[prop];
89
346
  const value = Reflect.get(obj, prop);
90
347
  if (accessObserver) accessObserver(receiver, prop);
91
- let dep = depsMap.get(prop);
92
- if (!dep) {
93
- dep = /* @__PURE__ */ new Set();
94
- depsMap.set(prop, dep);
95
- }
96
- track(dep);
97
- if (value && typeof value === "object") {
348
+ if (!collectionInstrumentations) track(getOrCreateDep(prop));
349
+ if (value && typeof value === "object" && !shouldNotProxy(value)) {
98
350
  let cached = reactiveCache.get(value);
99
351
  if (!cached) {
100
352
  cached = signal(value);
@@ -134,28 +386,26 @@ function signal(target) {
134
386
  return result;
135
387
  }
136
388
  });
389
+ reactiveToRaw.set(proxy, objectTarget);
390
+ rawToReactive.set(objectTarget, proxy);
391
+ return proxy;
137
392
  }
138
- function effect(fn) {
139
- return runEffect(fn);
393
+ function traverse(value, depth = Infinity, seen = /* @__PURE__ */ new Set()) {
394
+ if (depth <= 0) return value;
395
+ if (value === null || typeof value !== "object") return value;
396
+ if (seen.has(value)) return value;
397
+ seen.add(value);
398
+ if (Array.isArray(value)) for (let i = 0; i < value.length; i++) traverse(value[i], depth - 1, seen);
399
+ else if (value instanceof Map) value.forEach((v, k) => {
400
+ traverse(k, depth - 1, seen);
401
+ traverse(v, depth - 1, seen);
402
+ });
403
+ else if (value instanceof Set) value.forEach((v) => {
404
+ traverse(v, depth - 1, seen);
405
+ });
406
+ else for (const key of Object.keys(value)) traverse(value[key], depth - 1, seen);
407
+ return value;
140
408
  }
141
- const arrayInstrumentations = {};
142
- [
143
- "push",
144
- "pop",
145
- "shift",
146
- "unshift",
147
- "splice",
148
- "sort",
149
- "reverse"
150
- ].forEach((method) => {
151
- arrayInstrumentations[method] = function(...args) {
152
- let res;
153
- batch(() => {
154
- res = Array.prototype[method].apply(this, args);
155
- });
156
- return res;
157
- };
158
- });
159
409
  function watch(source, cb, options) {
160
410
  let oldValue;
161
411
  let isFirst = true;
@@ -163,8 +413,13 @@ function watch(source, cb, options) {
163
413
  let paused = false;
164
414
  let pendingValue;
165
415
  let hasPending = false;
416
+ let stopped = false;
417
+ const deep = options?.deep;
418
+ const traverseDepth = deep === true ? Infinity : typeof deep === "number" ? deep : 0;
166
419
  const runner = effect(() => {
167
- const newValue = typeof source === "function" ? source() : source;
420
+ if (stopped) return;
421
+ let newValue = typeof source === "function" ? source() : source;
422
+ if (traverseDepth > 0) traverse(newValue, traverseDepth);
168
423
  if (paused) {
169
424
  pendingValue = newValue;
170
425
  hasPending = true;
@@ -174,15 +429,24 @@ function watch(source, cb, options) {
174
429
  if (options?.immediate) {
175
430
  if (cleanupFn) cleanupFn();
176
431
  cb(newValue, oldValue, (fn) => cleanupFn = fn);
432
+ if (options?.once) {
433
+ stopped = true;
434
+ queueMicrotask(() => stop());
435
+ }
177
436
  }
178
437
  isFirst = false;
179
438
  } else {
180
439
  if (cleanupFn) cleanupFn();
181
440
  cb(newValue, oldValue, (fn) => cleanupFn = fn);
441
+ if (options?.once) {
442
+ stopped = true;
443
+ queueMicrotask(() => stop());
444
+ }
182
445
  }
183
446
  oldValue = newValue;
184
447
  });
185
448
  const stop = () => {
449
+ stopped = true;
186
450
  runner.stop();
187
451
  if (cleanupFn) cleanupFn();
188
452
  };
@@ -206,124 +470,201 @@ function watch(source, cb, options) {
206
470
  resume
207
471
  });
208
472
  }
209
- function effectScope(detached) {
210
- const effects = [];
211
- let active = true;
212
- return {
213
- run(fn) {
214
- if (!active) return void 0;
215
- return fn();
216
- },
217
- stop() {
218
- active = false;
219
- effects.forEach((e) => e());
473
+ function computed(getterOrOptions) {
474
+ let getter;
475
+ let setter;
476
+ if (typeof getterOrOptions === "function") getter = getterOrOptions;
477
+ else {
478
+ getter = getterOrOptions.get;
479
+ setter = getterOrOptions.set;
480
+ }
481
+ const subscribers = /* @__PURE__ */ new Set();
482
+ let cachedValue;
483
+ let dirty = true;
484
+ const computedEffect = function() {
485
+ if (!dirty) {
486
+ dirty = true;
487
+ trigger(subscribers);
488
+ }
489
+ };
490
+ computedEffect.deps = [];
491
+ const computeValue = () => {
492
+ cleanup(computedEffect);
493
+ const prevEffect = getActiveEffect();
494
+ setActiveEffect(computedEffect);
495
+ try {
496
+ cachedValue = getter();
497
+ dirty = false;
498
+ return cachedValue;
499
+ } finally {
500
+ setActiveEffect(prevEffect);
220
501
  }
221
502
  };
503
+ const computedObj = {
504
+ [ComputedSymbol]: true,
505
+ get value() {
506
+ const observer = getAccessObserver();
507
+ if (observer) observer(computedObj, "value");
508
+ track(subscribers);
509
+ return dirty ? computeValue() : cachedValue;
510
+ }
511
+ };
512
+ if (setter) {
513
+ Object.defineProperty(computedObj, "value", {
514
+ get() {
515
+ const observer = getAccessObserver();
516
+ if (observer) observer(computedObj, "value");
517
+ track(subscribers);
518
+ return dirty ? computeValue() : cachedValue;
519
+ },
520
+ set(newValue) {
521
+ setter(newValue);
522
+ },
523
+ enumerable: true,
524
+ configurable: false
525
+ });
526
+ return computedObj;
527
+ }
528
+ return computedObj;
222
529
  }
223
-
224
- //#endregion
225
- //#region ../runtime-core/src/platform.ts
226
- let platformSyncProcessor$1 = null;
227
- /**
228
- * Set the platform-specific sync processor for intrinsic elements.
229
- * Called by runtime-dom to handle checkbox/radio/select sync bindings.
230
- */
231
- function setPlatformSyncProcessor(fn) {
232
- platformSyncProcessor$1 = fn;
233
- }
234
- /**
235
- * Get the current platform sync processor (for internal use).
236
- */
237
- function getPlatformSyncProcessor() {
238
- return platformSyncProcessor$1;
530
+ function isComputed(value) {
531
+ return value !== null && typeof value === "object" && ComputedSymbol in value;
239
532
  }
240
-
241
- //#endregion
242
- //#region ../runtime-core/src/plugins.ts
243
- const plugins$1 = [];
533
+ var platformModelProcessor = null;
534
+ function setPlatformModelProcessor(fn) {
535
+ platformModelProcessor = fn;
536
+ }
537
+ function getPlatformModelProcessor() {
538
+ return platformModelProcessor;
539
+ }
540
+ var plugins = [];
244
541
  function registerComponentPlugin(plugin) {
245
- plugins$1.push(plugin);
542
+ plugins.push(plugin);
246
543
  }
247
- /**
248
- * Get all registered plugins (internal use)
249
- */
250
544
  function getComponentPlugins() {
251
- return plugins$1;
252
- }
253
- const contextExtensions = [];
254
- /**
255
- * Register a function that will be called to extend every component context.
256
- * Extensions are called in order of registration.
257
- *
258
- * @example
259
- * ```ts
260
- * // In @sigx/server-renderer/client
261
- * registerContextExtension((ctx) => {
262
- * ctx.ssr = { load: () => {} };
263
- * });
264
- * ```
265
- */
545
+ return plugins;
546
+ }
547
+ var contextExtensions = [];
266
548
  function registerContextExtension(extension) {
267
549
  contextExtensions.push(extension);
268
550
  }
269
- /**
270
- * Apply all registered context extensions to a context object.
271
- * Called internally by the renderer when creating component contexts.
272
- */
273
551
  function applyContextExtensions(ctx) {
274
552
  for (const extension of contextExtensions) extension(ctx);
275
553
  }
276
-
277
- //#endregion
278
- //#region ../runtime-core/src/app.ts
279
- const isDev = typeof process !== "undefined" && true || true;
280
- /**
281
- * Unique symbol for app context injection
282
- */
283
- const AppContextKey = Symbol("sigx:app");
284
- let defaultMountFn = null;
285
- /**
286
- * Set the default mount function for the platform.
287
- * Called by platform packages (runtime-dom, runtime-terminal) on import.
288
- *
289
- * @example
290
- * ```typescript
291
- * // In @sigx/runtime-dom
292
- * import { setDefaultMount } from '@sigx/runtime-core';
293
- * setDefaultMount(domMount);
294
- * ```
295
- */
554
+ var currentComponentContext = null;
555
+ function getCurrentInstance() {
556
+ return currentComponentContext;
557
+ }
558
+ function setCurrentInstance(ctx) {
559
+ const prev = currentComponentContext;
560
+ currentComponentContext = ctx;
561
+ return prev;
562
+ }
563
+ function onMounted(fn) {
564
+ if (currentComponentContext) currentComponentContext.onMounted(fn);
565
+ else console.warn("onMounted called outside of component setup");
566
+ }
567
+ function onUnmounted(fn) {
568
+ if (currentComponentContext) currentComponentContext.onUnmounted(fn);
569
+ else console.warn("onUnmounted called outside of component setup");
570
+ }
571
+ function onCreated(fn) {
572
+ if (currentComponentContext) currentComponentContext.onCreated(fn);
573
+ else console.warn("onCreated called outside of component setup");
574
+ }
575
+ function onUpdated(fn) {
576
+ if (currentComponentContext) currentComponentContext.onUpdated(fn);
577
+ else console.warn("onUpdated called outside of component setup");
578
+ }
579
+ var componentRegistry = /* @__PURE__ */ new Map();
580
+ function getComponentMeta(factory) {
581
+ return componentRegistry.get(factory);
582
+ }
583
+ function createPropsProxy(target, onAccess) {
584
+ return new Proxy(target, { get(obj, prop) {
585
+ if (typeof prop === "string" && onAccess) onAccess(prop);
586
+ return obj[prop];
587
+ } });
588
+ }
589
+ function component(setup, options) {
590
+ const factory = function(props) {
591
+ return {
592
+ type: factory,
593
+ props: props || {},
594
+ key: props?.key || null,
595
+ children: [],
596
+ dom: null
597
+ };
598
+ };
599
+ factory.__setup = setup;
600
+ factory.__name = options?.name;
601
+ factory.__props = null;
602
+ factory.__events = null;
603
+ factory.__ref = null;
604
+ factory.__slots = null;
605
+ componentRegistry.set(factory, {
606
+ name: options?.name,
607
+ setup
608
+ });
609
+ getComponentPlugins().forEach((p) => p.onDefine?.(options?.name, factory, setup));
610
+ return factory;
611
+ }
612
+ var globalInstances = /* @__PURE__ */ new Map();
613
+ var appContextToken = Symbol("sigx:appContext");
614
+ function lookupProvided(token) {
615
+ const ctx = getCurrentInstance();
616
+ if (!ctx) return;
617
+ let current = ctx;
618
+ while (current) {
619
+ if (current.provides && current.provides.has(token)) return current.provides.get(token);
620
+ current = current.parent;
621
+ }
622
+ }
623
+ function provideAtComponent(token, value) {
624
+ const ctx = getCurrentInstance();
625
+ if (!ctx) throw new Error("defineProvide must be called inside a component setup function");
626
+ if (!ctx.provides) ctx.provides = /* @__PURE__ */ new Map();
627
+ ctx.provides.set(token, value);
628
+ }
629
+ function defineInjectable(factory) {
630
+ const token = Symbol();
631
+ const useFn = (() => {
632
+ const provided = lookupProvided(token);
633
+ if (provided !== void 0) return provided;
634
+ if (!globalInstances.has(token)) globalInstances.set(token, factory());
635
+ return globalInstances.get(token);
636
+ });
637
+ useFn._factory = factory;
638
+ useFn._token = token;
639
+ return useFn;
640
+ }
641
+ function defineProvide(useFn, factory) {
642
+ const actualFactory = factory ?? useFn._factory;
643
+ const token = useFn._token;
644
+ if (!actualFactory || !token) throw new Error("defineProvide must be called with a function created by defineInjectable");
645
+ const instance = actualFactory();
646
+ provideAtComponent(token, instance);
647
+ return instance;
648
+ }
649
+ function useAppContext() {
650
+ return lookupProvided(appContextToken) ?? null;
651
+ }
652
+ function getAppContextToken() {
653
+ return appContextToken;
654
+ }
655
+ function provideAppContext(ctx, appContext) {
656
+ if (!ctx.provides) ctx.provides = /* @__PURE__ */ new Map();
657
+ ctx.provides.set(appContextToken, appContext);
658
+ if (appContext.provides) for (const [token, value] of appContext.provides) ctx.provides.set(token, value);
659
+ }
660
+ var isDev = typeof process !== "undefined" && process.env.NODE_ENV !== "production" || true;
661
+ var defaultMountFn = null;
296
662
  function setDefaultMount(mountFn) {
297
663
  defaultMountFn = mountFn;
298
664
  }
299
- /**
300
- * Get the current default mount function.
301
- * @internal
302
- */
303
665
  function getDefaultMount() {
304
666
  return defaultMountFn;
305
667
  }
306
- /**
307
- * Create an application instance.
308
- *
309
- * @example
310
- * ```tsx
311
- * import { defineApp, defineInjectable } from '@sigx/runtime-core';
312
- * import { render } from '@sigx/runtime-dom';
313
- *
314
- * // Define an injectable service
315
- * const useApiConfig = defineInjectable(() => ({ baseUrl: 'https://api.example.com' }));
316
- *
317
- * const app = defineApp(<App />);
318
- *
319
- * app.use(myPlugin, { option: 'value' });
320
- *
321
- * // Provide using the injectable token (works with inject())
322
- * app.provide(useApiConfig, { baseUrl: 'https://custom.api.com' });
323
- *
324
- * app.mount(document.getElementById('app')!, render);
325
- * ```
326
- */
327
668
  function defineApp(rootComponent) {
328
669
  const installedPlugins = /* @__PURE__ */ new Set();
329
670
  const context = {
@@ -334,7 +675,7 @@ function defineApp(rootComponent) {
334
675
  };
335
676
  let isMounted = false;
336
677
  let container = null;
337
- let unmountFn$1 = null;
678
+ let unmountFn = null;
338
679
  const app = {
339
680
  config: context.config,
340
681
  use(plugin, options) {
@@ -348,11 +689,13 @@ function defineApp(rootComponent) {
348
689
  else if (isDev) console.warn("Invalid plugin: must be a function or have an install() method.");
349
690
  return app;
350
691
  },
351
- provide(token, value) {
352
- const actualToken = token?._token ?? token;
353
- if (isDev && context.provides.has(actualToken)) console.warn(`App-level provide: token is being overwritten.`);
354
- context.provides.set(actualToken, value);
355
- return app;
692
+ defineProvide(useFn, factory) {
693
+ const actualFactory = factory ?? useFn._factory;
694
+ const token = useFn._token;
695
+ if (!actualFactory || !token) throw new Error("defineProvide must be called with a function created by defineInjectable");
696
+ const instance = actualFactory();
697
+ context.provides.set(token, instance);
698
+ return instance;
356
699
  },
357
700
  hook(hooks) {
358
701
  context.hooks.push(hooks);
@@ -368,7 +711,7 @@ function defineApp(rootComponent) {
368
711
  container = target;
369
712
  isMounted = true;
370
713
  const result = mountFn(rootComponent, target, context);
371
- if (typeof result === "function") unmountFn$1 = result;
714
+ if (typeof result === "function") unmountFn = result;
372
715
  return app;
373
716
  },
374
717
  unmount() {
@@ -376,7 +719,7 @@ function defineApp(rootComponent) {
376
719
  if (isDev) console.warn("App is not mounted.");
377
720
  return;
378
721
  }
379
- if (unmountFn$1) unmountFn$1();
722
+ if (unmountFn) unmountFn();
380
723
  context.provides.clear();
381
724
  isMounted = false;
382
725
  container = null;
@@ -389,15 +732,16 @@ function defineApp(rootComponent) {
389
732
  },
390
733
  get _container() {
391
734
  return container;
735
+ },
736
+ get _rootComponent() {
737
+ return rootComponent;
392
738
  }
393
739
  };
394
740
  context.app = app;
741
+ const appContextToken = getAppContextToken();
742
+ context.provides.set(appContextToken, context);
395
743
  return app;
396
744
  }
397
- /**
398
- * Notify all app hooks that a component was created.
399
- * Called by the renderer after setup() returns.
400
- */
401
745
  function notifyComponentCreated(context, instance) {
402
746
  if (!context) return;
403
747
  for (const hooks of context.hooks) try {
@@ -406,10 +750,6 @@ function notifyComponentCreated(context, instance) {
406
750
  handleHookError(context, err, instance, "onComponentCreated");
407
751
  }
408
752
  }
409
- /**
410
- * Notify all app hooks that a component was mounted.
411
- * Called by the renderer after mount hooks run.
412
- */
413
753
  function notifyComponentMounted(context, instance) {
414
754
  if (!context) return;
415
755
  for (const hooks of context.hooks) try {
@@ -418,10 +758,6 @@ function notifyComponentMounted(context, instance) {
418
758
  handleHookError(context, err, instance, "onComponentMounted");
419
759
  }
420
760
  }
421
- /**
422
- * Notify all app hooks that a component was unmounted.
423
- * Called by the renderer before cleanup.
424
- */
425
761
  function notifyComponentUnmounted(context, instance) {
426
762
  if (!context) return;
427
763
  for (const hooks of context.hooks) try {
@@ -430,10 +766,6 @@ function notifyComponentUnmounted(context, instance) {
430
766
  handleHookError(context, err, instance, "onComponentUnmounted");
431
767
  }
432
768
  }
433
- /**
434
- * Notify all app hooks that a component updated.
435
- * Called by the renderer after re-render.
436
- */
437
769
  function notifyComponentUpdated(context, instance) {
438
770
  if (!context) return;
439
771
  for (const hooks of context.hooks) try {
@@ -442,10 +774,6 @@ function notifyComponentUpdated(context, instance) {
442
774
  handleHookError(context, err, instance, "onComponentUpdated");
443
775
  }
444
776
  }
445
- /**
446
- * Handle an error in a component. Returns true if the error was handled.
447
- * Called by the renderer when an error occurs in setup or render.
448
- */
449
777
  function handleComponentError(context, err, instance, info) {
450
778
  if (!context) return false;
451
779
  for (const hooks of context.hooks) try {
@@ -460,105 +788,54 @@ function handleComponentError(context, err, instance, info) {
460
788
  }
461
789
  return false;
462
790
  }
463
- /**
464
- * Handle errors that occur in hooks themselves
465
- */
466
791
  function handleHookError(context, err, instance, hookName) {
467
792
  console.error(`Error in ${hookName} hook:`, err);
468
793
  if (context.config.errorHandler) try {
469
794
  context.config.errorHandler(err, instance, `plugin hook: ${hookName}`);
470
795
  } catch {}
471
796
  }
472
-
473
- //#endregion
474
- //#region ../runtime-core/src/component.ts
475
- let currentComponentContext = null;
476
- function getCurrentInstance() {
477
- return currentComponentContext;
478
- }
479
- function setCurrentInstance(ctx) {
480
- const prev = currentComponentContext;
481
- currentComponentContext = ctx;
482
- return prev;
797
+ function compound(main, sub) {
798
+ return Object.assign(main, sub);
483
799
  }
484
- function onMount(fn) {
485
- if (currentComponentContext) currentComponentContext.onMount(fn);
486
- else console.warn("onMount called outside of component setup");
800
+ var MODEL_SYMBOL = Symbol.for("sigx.model");
801
+ function createModel(tuple, updateHandler) {
802
+ const [obj, key] = tuple;
803
+ return {
804
+ get value() {
805
+ return obj[key];
806
+ },
807
+ set value(v) {
808
+ updateHandler(v);
809
+ },
810
+ get binding() {
811
+ return [
812
+ obj,
813
+ key,
814
+ updateHandler
815
+ ];
816
+ },
817
+ [MODEL_SYMBOL]: true
818
+ };
487
819
  }
488
- function onCleanup(fn) {
489
- if (currentComponentContext) currentComponentContext.onCleanup(fn);
490
- else console.warn("onCleanup called outside of component setup");
820
+ function createModelFromBinding(binding) {
821
+ const [obj, key, handler] = binding;
822
+ return createModel([obj, key], handler);
491
823
  }
492
- const componentRegistry$1 = /* @__PURE__ */ new Map();
493
- /**
494
- * Get component metadata (for DevTools)
495
- */
496
- function getComponentMeta(factory) {
497
- return componentRegistry$1.get(factory);
824
+ function isModel(value) {
825
+ return value !== null && typeof value === "object" && MODEL_SYMBOL in value && value[MODEL_SYMBOL] === true;
498
826
  }
499
- /**
500
- * Helper to create a proxy that tracks property access
501
- */
502
- function createPropsProxy(target, onAccess) {
503
- return new Proxy(target, { get(obj, prop) {
504
- if (typeof prop === "string" && onAccess) onAccess(prop);
505
- return obj[prop];
506
- } });
827
+ function getModelSymbol() {
828
+ return MODEL_SYMBOL;
507
829
  }
508
- /**
509
- * Define a component. Returns a JSX factory function.
510
- *
511
- * @param setup - Setup function that receives context and returns a render function
512
- * @param options - Optional configuration (e.g., name for DevTools)
513
- *
514
- * @example
515
- * ```tsx
516
- * type CardProps = DefineProp<"title", string> & DefineSlot<"header">;
517
- *
518
- * export const Card = defineComponent<CardProps>((ctx) => {
519
- * const { title } = ctx.props;
520
- * const { slots } = ctx;
521
- *
522
- * return () => (
523
- * <div class="card">
524
- * {slots.header?.() ?? <h2>{title}</h2>}
525
- * {slots.default()}
526
- * </div>
527
- * );
528
- * });
529
- * ```
530
- */
531
- function defineComponent(setup, options) {
532
- const factory = function(props) {
533
- return {
534
- type: factory,
535
- props: props || {},
536
- key: props?.key || null,
537
- children: [],
538
- dom: null
539
- };
540
- };
541
- factory.__setup = setup;
542
- factory.__name = options?.name;
543
- factory.__props = null;
544
- factory.__events = null;
545
- factory.__ref = null;
546
- factory.__slots = null;
547
- componentRegistry$1.set(factory, {
548
- name: options?.name,
549
- setup
550
- });
551
- getComponentPlugins().forEach((p) => p.onDefine?.(options?.name, factory, setup));
552
- return factory;
830
+ function isComponent(type) {
831
+ return typeof type === "function" && "__setup" in type;
553
832
  }
554
-
555
- //#endregion
556
- //#region ../runtime-core/src/jsx-runtime.ts
557
833
  const Fragment = Symbol.for("sigx.Fragment");
558
834
  const Text = Symbol.for("sigx.Text");
559
- function normalizeChildren$1(children) {
835
+ function normalizeChildren(children) {
560
836
  if (children == null || children === false || children === true) return [];
561
- if (Array.isArray(children)) return children.flatMap((c) => normalizeChildren$1(c));
837
+ if (isComputed(children)) return normalizeChildren(children.value);
838
+ if (Array.isArray(children)) return children.flatMap((c) => normalizeChildren(c));
562
839
  if (typeof children === "string" || typeof children === "number") return [{
563
840
  type: Text,
564
841
  props: {},
@@ -570,64 +847,92 @@ function normalizeChildren$1(children) {
570
847
  if (children.type) return [children];
571
848
  return [];
572
849
  }
573
- /**
574
- * Check if a type is a sigx component (has __setup)
575
- */
576
- function isComponent$2(type) {
577
- return typeof type === "function" && "__setup" in type;
578
- }
579
- /**
580
- * Create a JSX element - this is the core function called by TSX transpilation
581
- */
582
850
  function jsx(type, props, key) {
583
851
  const processedProps = { ...props || {} };
852
+ const models = {};
853
+ const isComponentType = isComponent(type);
584
854
  if (props) {
585
- for (const propKey in props) if (propKey === "sync") {
586
- let syncBinding = props[propKey];
587
- if (typeof syncBinding === "function") {
588
- const detected = detectAccess(syncBinding);
589
- if (detected) syncBinding = detected;
590
- }
591
- if (Array.isArray(syncBinding) && syncBinding.length === 2) {
592
- const [stateObj, key$1] = syncBinding;
855
+ for (const propKey in props) if (propKey === "model") {
856
+ let modelBinding = props[propKey];
857
+ let tuple = null;
858
+ let updateHandler = null;
859
+ if (isModel(modelBinding)) {
860
+ const [obj, key, handler] = modelBinding.binding;
861
+ tuple = [obj, key];
862
+ updateHandler = handler;
863
+ } else if (typeof modelBinding === "function") {
864
+ const detected = detectAccess(modelBinding);
865
+ if (detected && typeof detected[1] === "string") tuple = detected;
866
+ } else if (Array.isArray(modelBinding) && modelBinding.length === 2 && typeof modelBinding[1] === "string") tuple = modelBinding;
867
+ if (tuple) {
868
+ const [stateObj, stateKey] = tuple;
593
869
  let handled = false;
594
- const platformProcessor = getPlatformSyncProcessor();
595
- if (typeof type === "string" && platformProcessor) handled = platformProcessor(type, processedProps, [stateObj, key$1], props);
596
- if (!handled) {
597
- processedProps.value = stateObj[key$1];
598
- const existingHandler = processedProps["onUpdate:value"];
599
- processedProps["onUpdate:value"] = (v) => {
600
- stateObj[key$1] = v;
870
+ if (!updateHandler) {
871
+ const existingHandler = processedProps["onUpdate:modelValue"];
872
+ updateHandler = (v) => {
873
+ const customHandler = stateObj[`onUpdate:${stateKey}`];
874
+ if (typeof customHandler === "function") customHandler(v);
875
+ else stateObj[stateKey] = v;
601
876
  if (existingHandler) existingHandler(v);
602
877
  };
603
878
  }
604
- delete processedProps.sync;
879
+ const platformProcessor = getPlatformModelProcessor();
880
+ if (typeof type === "string" && platformProcessor) handled = platformProcessor(type, processedProps, tuple, props);
881
+ if (isComponentType) {
882
+ models.model = createModel(tuple, updateHandler);
883
+ processedProps["onUpdate:modelValue"] = updateHandler;
884
+ } else if (!handled) {
885
+ processedProps.modelValue = stateObj[stateKey];
886
+ processedProps["onUpdate:modelValue"] = updateHandler;
887
+ }
888
+ delete processedProps.model;
605
889
  }
606
- } else if (propKey.startsWith("sync:")) {
607
- const syncBinding = props[propKey];
608
- if (Array.isArray(syncBinding) && syncBinding.length === 2) {
609
- const [stateObj, key$1] = syncBinding;
610
- const name = propKey.slice(5);
611
- processedProps[name] = stateObj[key$1];
890
+ } else if (propKey.startsWith("model:")) {
891
+ let modelBinding = props[propKey];
892
+ const name = propKey.slice(6);
893
+ let tuple = null;
894
+ let updateHandler = null;
895
+ if (isModel(modelBinding)) {
896
+ const [obj, key, handler] = modelBinding.binding;
897
+ tuple = [obj, key];
898
+ updateHandler = handler;
899
+ } else if (typeof modelBinding === "function") {
900
+ const detected = detectAccess(modelBinding);
901
+ if (detected && typeof detected[1] === "string") tuple = detected;
902
+ } else if (Array.isArray(modelBinding) && modelBinding.length === 2 && typeof modelBinding[1] === "string") tuple = modelBinding;
903
+ if (tuple) {
904
+ const [stateObj, stateKey] = tuple;
612
905
  const eventName = `onUpdate:${name}`;
613
- const existingHandler = processedProps[eventName];
614
- processedProps[eventName] = (v) => {
615
- stateObj[key$1] = v;
616
- if (existingHandler) existingHandler(v);
617
- };
906
+ if (!updateHandler) {
907
+ const existingHandler = processedProps[eventName];
908
+ updateHandler = (v) => {
909
+ const customHandler = stateObj[`onUpdate:${stateKey}`];
910
+ if (typeof customHandler === "function") customHandler(v);
911
+ else stateObj[stateKey] = v;
912
+ if (existingHandler) existingHandler(v);
913
+ };
914
+ }
915
+ if (isComponentType) {
916
+ models[name] = createModel(tuple, updateHandler);
917
+ processedProps[eventName] = updateHandler;
918
+ } else {
919
+ processedProps[name] = stateObj[stateKey];
920
+ processedProps[eventName] = updateHandler;
921
+ }
618
922
  delete processedProps[propKey];
619
923
  }
620
924
  }
621
925
  }
622
- if (isComponent$2(type)) {
623
- const { children: children$1, ...rest$1 } = processedProps;
926
+ if (Object.keys(models).length > 0) processedProps.$models = models;
927
+ if (isComponent(type)) {
928
+ const { children, ...rest } = processedProps;
624
929
  return {
625
930
  type,
626
931
  props: {
627
- ...rest$1,
628
- children: children$1
932
+ ...rest,
933
+ children
629
934
  },
630
- key: key || rest$1.key || null,
935
+ key: key || rest.key || null,
631
936
  children: [],
632
937
  dom: null
633
938
  };
@@ -638,33 +943,17 @@ function jsx(type, props, key) {
638
943
  type,
639
944
  props: rest,
640
945
  key: key || rest.key || null,
641
- children: normalizeChildren$1(children),
946
+ children: normalizeChildren(children),
642
947
  dom: null
643
948
  };
644
949
  }
645
- /**
646
- * JSX Factory for fragments
647
- */
648
950
  function jsxs(type, props, key) {
649
951
  return jsx(type, props, key);
650
952
  }
651
953
  const jsxDEV = jsx;
652
-
653
- //#endregion
654
- //#region ../runtime-core/src/lazy.tsx
655
- /**
656
- * Lazy loading utilities for sigx components.
657
- *
658
- * Provides runtime-only lazy loading with no build dependencies.
659
- * Works with any bundler that supports dynamic import().
660
- */
661
- let currentSuspenseBoundary$1 = null;
662
- /**
663
- * Register a promise with the current Suspense boundary
664
- * @internal
665
- */
954
+ var currentSuspenseBoundary = null;
666
955
  function registerPendingPromise(promise) {
667
- const boundary = currentSuspenseBoundary$1;
956
+ const boundary = currentSuspenseBoundary;
668
957
  if (boundary) {
669
958
  boundary.pending.add(promise);
670
959
  promise.finally(() => {
@@ -675,39 +964,12 @@ function registerPendingPromise(promise) {
675
964
  }
676
965
  return false;
677
966
  }
678
- /**
679
- * Create a lazy-loaded component wrapper.
680
- *
681
- * The component will be loaded on first render. Use with `<Suspense>` to show
682
- * a fallback while loading.
683
- *
684
- * @param loader - Function that returns a Promise resolving to the component
685
- * @returns A component factory that loads the real component on demand
686
- *
687
- * @example
688
- * ```tsx
689
- * import { lazy, Suspense } from 'sigx';
690
- *
691
- * // Component will be in a separate chunk
692
- * const HeavyChart = lazy(() => import('./components/HeavyChart'));
693
- *
694
- * // Usage
695
- * <Suspense fallback={<Spinner />}>
696
- * <HeavyChart data={chartData} />
697
- * </Suspense>
698
- *
699
- * // Preload on hover
700
- * <button onMouseEnter={() => HeavyChart.preload()}>
701
- * Show Chart
702
- * </button>
703
- * ```
704
- */
705
967
  function lazy(loader) {
706
968
  let Component = null;
707
969
  let promise = null;
708
970
  let error = null;
709
971
  let state = "pending";
710
- const LazyWrapper = defineComponent((ctx) => {
972
+ const LazyWrapper = component((ctx) => {
711
973
  const loadState = ctx.signal({
712
974
  state,
713
975
  tick: 0
@@ -756,30 +1018,7 @@ function lazy(loader) {
756
1018
  };
757
1019
  return LazyWrapper;
758
1020
  }
759
- /**
760
- * Suspense boundary component for handling async loading states.
761
- *
762
- * Wraps lazy-loaded components and shows a fallback while they load.
763
- *
764
- * @example
765
- * ```tsx
766
- * import { lazy, Suspense } from 'sigx';
767
- *
768
- * const LazyDashboard = lazy(() => import('./Dashboard'));
769
- *
770
- * // Basic usage
771
- * <Suspense fallback={<div>Loading...</div>}>
772
- * <LazyDashboard />
773
- * </Suspense>
774
- *
775
- * // With spinner component
776
- * <Suspense fallback={<Spinner size="large" />}>
777
- * <LazyDashboard />
778
- * <LazyCharts />
779
- * </Suspense>
780
- * ```
781
- */
782
- const Suspense = defineComponent((ctx) => {
1021
+ const Suspense = component((ctx) => {
783
1022
  const { props, slots } = ctx;
784
1023
  const state = ctx.signal({
785
1024
  isReady: false,
@@ -792,14 +1031,14 @@ const Suspense = defineComponent((ctx) => {
792
1031
  if (boundary.pending.size === 0) state.isReady = true;
793
1032
  }
794
1033
  };
795
- ctx.onMount(() => {
1034
+ ctx.onMounted(() => {
796
1035
  if (boundary.pending.size === 0) state.isReady = true;
797
1036
  });
798
1037
  return () => {
799
1038
  state.isReady;
800
1039
  state.pendingCount;
801
- const prevBoundary = currentSuspenseBoundary$1;
802
- currentSuspenseBoundary$1 = boundary;
1040
+ const prevBoundary = currentSuspenseBoundary;
1041
+ currentSuspenseBoundary = boundary;
803
1042
  try {
804
1043
  const children = slots.default();
805
1044
  if (boundary.pending.size > 0) {
@@ -823,19 +1062,13 @@ const Suspense = defineComponent((ctx) => {
823
1062
  }
824
1063
  throw err;
825
1064
  } finally {
826
- currentSuspenseBoundary$1 = prevBoundary;
1065
+ currentSuspenseBoundary = prevBoundary;
827
1066
  }
828
1067
  };
829
1068
  }, { name: "Suspense" });
830
- /**
831
- * Check if a component is a lazy-loaded component
832
- */
833
1069
  function isLazyComponent(component) {
834
1070
  return component && component.__lazy === true;
835
1071
  }
836
-
837
- //#endregion
838
- //#region ../runtime-core/src/utils/index.ts
839
1072
  var Utils = class {
840
1073
  static isPromise(value) {
841
1074
  return !!value && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
@@ -847,92 +1080,29 @@ function guid$1() {
847
1080
  return (c == "x" ? r : r & 3 | 8).toString(16);
848
1081
  });
849
1082
  }
850
-
851
- //#endregion
852
- //#region ../runtime-core/src/utils/props-accessor.ts
853
- /**
854
- * Creates a props accessor that can be called with defaults or accessed directly.
855
- * After calling with defaults, direct property access uses those defaults.
856
- *
857
- * @example
858
- * ```ts
859
- * // In component setup:
860
- * const props = createPropsAccessor(reactiveProps);
861
- *
862
- * // Set defaults
863
- * props({ count: 0, label: 'Default' });
864
- *
865
- * // Access props (falls back to defaults if not provided)
866
- * const count = props.count;
867
- * ```
868
- */
869
1083
  function createPropsAccessor(reactiveProps) {
870
- let defaults = {};
871
- const proxy = new Proxy(function propsAccessor() {}, {
872
- get(_, key) {
1084
+ return new Proxy(reactiveProps, {
1085
+ get(target, key) {
873
1086
  if (typeof key === "symbol") return void 0;
874
- const value = reactiveProps[key];
875
- return value != null ? value : defaults[key];
876
- },
877
- apply(_, __, args) {
878
- if (args[0] && typeof args[0] === "object") defaults = {
879
- ...defaults,
880
- ...args[0]
881
- };
882
- return proxy;
1087
+ return target[key];
883
1088
  },
884
- has(_, key) {
1089
+ has(target, key) {
885
1090
  if (typeof key === "symbol") return false;
886
- return key in reactiveProps || key in defaults;
1091
+ return key in target;
887
1092
  },
888
- ownKeys() {
889
- return [...new Set([...Object.keys(reactiveProps), ...Object.keys(defaults)])];
1093
+ ownKeys(target) {
1094
+ return Object.keys(target);
890
1095
  },
891
- getOwnPropertyDescriptor(_, key) {
1096
+ getOwnPropertyDescriptor(target, key) {
892
1097
  if (typeof key === "symbol") return void 0;
893
- if (key in reactiveProps || key in defaults) return {
1098
+ if (key in target) return {
894
1099
  enumerable: true,
895
1100
  configurable: true,
896
1101
  writable: false
897
1102
  };
898
1103
  }
899
1104
  });
900
- return proxy;
901
1105
  }
902
-
903
- //#endregion
904
- //#region ../runtime-core/src/utils/slots.ts
905
- /**
906
- * Slots system for component children.
907
- * Supports default and named slots with reactivity.
908
- */
909
- /**
910
- * Create slots object from children and slots prop.
911
- * Uses a version signal to trigger re-renders when children change.
912
- *
913
- * Supports named slots via:
914
- * - `slots` prop object (e.g., `slots={{ header: () => <div>...</div> }}`)
915
- * - `slot` prop on children (e.g., `<div slot="header">...</div>`)
916
- *
917
- * @example
918
- * ```tsx
919
- * // Parent component
920
- * <Card slots={{ header: () => <h1>Title</h1> }}>
921
- * <p>Default content</p>
922
- * <span slot="footer">Footer text</span>
923
- * </Card>
924
- *
925
- * // Card component setup
926
- * const slots = createSlots(children, slotsFromProps);
927
- * return () => (
928
- * <div>
929
- * {slots.header()}
930
- * {slots.default()}
931
- * {slots.footer()}
932
- * </div>
933
- * );
934
- * ```
935
- */
936
1106
  function createSlots(children, slotsFromProps) {
937
1107
  const versionSignal = signal({ v: 0 });
938
1108
  function extractNamedSlotsFromChildren(c) {
@@ -979,37 +1149,6 @@ function createSlots(children, slotsFromProps) {
979
1149
  };
980
1150
  } });
981
1151
  }
982
-
983
- //#endregion
984
- //#region ../runtime-core/src/utils/normalize.ts
985
- /**
986
- * VNode normalization utilities.
987
- * Converts render results into proper VNode structures.
988
- */
989
- /**
990
- * Normalize render result to a VNode (wrapping arrays in Fragment).
991
- * Handles null, undefined, false, true by returning an empty Text node.
992
- *
993
- * This is used to normalize the return value of component render functions
994
- * into a consistent VNode structure for the renderer to process.
995
- *
996
- * @example
997
- * ```ts
998
- * // Conditional rendering returns null/false
999
- * normalizeSubTree(null) // → empty Text node
1000
- * normalizeSubTree(false) // → empty Text node
1001
- *
1002
- * // Arrays become Fragments
1003
- * normalizeSubTree([<A/>, <B/>]) // → Fragment with children
1004
- *
1005
- * // Primitives become Text nodes
1006
- * normalizeSubTree("hello") // → Text node
1007
- * normalizeSubTree(42) // → Text node
1008
- *
1009
- * // VNodes pass through
1010
- * normalizeSubTree(<div/>) // → same VNode
1011
- * ```
1012
- */
1013
1152
  function normalizeSubTree(result) {
1014
1153
  if (result == null || result === false || result === true) return {
1015
1154
  type: Text,
@@ -1019,6 +1158,7 @@ function normalizeSubTree(result) {
1019
1158
  dom: null,
1020
1159
  text: ""
1021
1160
  };
1161
+ if (isComputed(result)) return normalizeSubTree(result.value);
1022
1162
  if (Array.isArray(result)) return {
1023
1163
  type: Fragment,
1024
1164
  props: {},
@@ -1036,22 +1176,16 @@ function normalizeSubTree(result) {
1036
1176
  };
1037
1177
  return result;
1038
1178
  }
1039
-
1040
- //#endregion
1041
- //#region ../runtime-core/src/models/index.ts
1042
1179
  const guid = guid$1;
1043
- let InstanceLifetimes = /* @__PURE__ */ function(InstanceLifetimes$1) {
1044
- InstanceLifetimes$1[InstanceLifetimes$1["Transient"] = 0] = "Transient";
1045
- InstanceLifetimes$1[InstanceLifetimes$1["Scoped"] = 1] = "Scoped";
1046
- InstanceLifetimes$1[InstanceLifetimes$1["Singleton"] = 2] = "Singleton";
1047
- return InstanceLifetimes$1;
1180
+ let InstanceLifetimes = /* @__PURE__ */ function(InstanceLifetimes) {
1181
+ InstanceLifetimes[InstanceLifetimes["Transient"] = 0] = "Transient";
1182
+ InstanceLifetimes[InstanceLifetimes["Scoped"] = 1] = "Scoped";
1183
+ InstanceLifetimes[InstanceLifetimes["Singleton"] = 2] = "Singleton";
1184
+ return InstanceLifetimes;
1048
1185
  }({});
1049
1186
  function valueOf(obj) {
1050
1187
  return obj;
1051
1188
  }
1052
-
1053
- //#endregion
1054
- //#region ../runtime-core/src/messaging/index.ts
1055
1189
  function createTopic(options) {
1056
1190
  let subscribers = [];
1057
1191
  const publish = (data) => {
@@ -1064,7 +1198,7 @@ function createTopic(options) {
1064
1198
  if (idx > -1) subscribers.splice(idx, 1);
1065
1199
  };
1066
1200
  try {
1067
- onCleanup(unsubscribe);
1201
+ onUnmounted(unsubscribe);
1068
1202
  } catch (e) {}
1069
1203
  return { unsubscribe };
1070
1204
  };
@@ -1080,72 +1214,10 @@ function createTopic(options) {
1080
1214
  function toSubscriber(topic) {
1081
1215
  return { subscribe: (handler) => topic.subscribe(handler) };
1082
1216
  }
1083
-
1084
- //#endregion
1085
- //#region ../runtime-core/src/di/injectable.ts
1086
- function inject(token) {
1087
- const ctx = getCurrentInstance();
1088
- if (!ctx) return void 0;
1089
- let current = ctx;
1090
- while (current) {
1091
- if (current.provides && current.provides.has(token)) return current.provides.get(token);
1092
- current = current.parent;
1093
- }
1094
- const appContext = getAppContext(ctx);
1095
- if (appContext && appContext.provides.has(token)) return appContext.provides.get(token);
1096
- }
1097
- /**
1098
- * Get the app context from the current component context
1099
- */
1100
- function getAppContext(ctx) {
1101
- let current = ctx;
1102
- while (current) {
1103
- if (current._appContext) return current._appContext;
1104
- current = current.parent;
1105
- }
1106
- return null;
1107
- }
1108
- /**
1109
- * Inject the App instance (useful for plugins)
1110
- */
1111
- function injectApp() {
1112
- return inject(AppContextKey);
1113
- }
1114
- function provide(token, value) {
1115
- const ctx = getCurrentInstance();
1116
- if (!ctx) {
1117
- console.warn("provide called outside of component setup");
1118
- return;
1119
- }
1120
- if (!ctx.provides) ctx.provides = /* @__PURE__ */ new Map();
1121
- ctx.provides.set(token, value);
1122
- }
1123
- const globalInstances = /* @__PURE__ */ new Map();
1124
- function defineInjectable(factory) {
1125
- const token = factory;
1126
- const useFn = () => {
1127
- const injected = inject(token);
1128
- if (injected) return injected;
1129
- if (!globalInstances.has(token)) globalInstances.set(token, factory());
1130
- return globalInstances.get(token);
1131
- };
1132
- useFn._factory = factory;
1133
- useFn._token = token;
1134
- return useFn;
1135
- }
1136
- function defineProvide(useFn) {
1137
- const factory = useFn._factory;
1138
- const token = useFn._token;
1139
- if (!factory || !token) throw new Error("defineProvide must be called with a function created by defineInjectable");
1140
- const instance = factory();
1141
- provide(token, instance);
1142
- return instance;
1143
- }
1144
-
1145
- //#endregion
1146
- //#region ../runtime-core/src/di/factory.ts
1147
1217
  var SubscriptionHandler = class {
1148
- unsubs = [];
1218
+ constructor() {
1219
+ this.unsubs = [];
1220
+ }
1149
1221
  add(unsub) {
1150
1222
  this.unsubs.push(unsub);
1151
1223
  }
@@ -1171,7 +1243,7 @@ function defineFactory(setup, lifetime, typeIdentifier) {
1171
1243
  };
1172
1244
  if (customDispose) customDispose(dispose);
1173
1245
  else try {
1174
- onCleanup(() => dispose());
1246
+ onUnmounted(() => dispose());
1175
1247
  } catch (e) {}
1176
1248
  return {
1177
1249
  ...result,
@@ -1181,160 +1253,64 @@ function defineFactory(setup, lifetime, typeIdentifier) {
1181
1253
  if (setup.length <= 1) return defineInjectable(() => factoryCreator());
1182
1254
  return factoryCreator;
1183
1255
  }
1184
-
1185
- //#endregion
1186
- //#region ../runtime-core/src/stores/store.ts
1187
- function defineStore(name, setup, lifetime = InstanceLifetimes.Scoped) {
1188
- return defineFactory((ctxFactory, ...args) => {
1189
- const scope = effectScope(true);
1190
- let messages = [];
1191
- const id = `${name}_${guid()}`;
1192
- const result = setup({
1193
- ...ctxFactory,
1194
- defineState: (state) => {
1195
- return defineState(state, id, scope, messages);
1196
- },
1197
- defineActions: (actions) => {
1198
- return defineActions(actions, id, messages);
1199
- }
1200
- }, ...args);
1201
- ctxFactory.onDeactivated(() => {
1202
- scope.stop();
1203
- messages?.forEach((m) => m.destroy());
1204
- messages = null;
1205
- });
1206
- if (!result.name) result.name = id;
1207
- return result;
1208
- }, lifetime);
1209
- }
1210
- function defineActions(actions, storeInstanceName, messages) {
1211
- const events = {};
1212
- const namespace = `${storeInstanceName}.actions.${guid()}`;
1213
- const onDispatching = {};
1214
- const onDispatched = {};
1215
- const onFailure = {};
1216
- const result = {
1217
- onDispatching,
1218
- onDispatched,
1219
- onFailure
1256
+ const CLIENT_DIRECTIVE_PREFIX = "client:";
1257
+ const CLIENT_DIRECTIVES = [
1258
+ "client:load",
1259
+ "client:idle",
1260
+ "client:visible",
1261
+ "client:media",
1262
+ "client:only"
1263
+ ];
1264
+ function filterClientDirectives(props) {
1265
+ const filtered = {};
1266
+ for (const key in props) if (!key.startsWith("client:")) filtered[key] = props[key];
1267
+ return filtered;
1268
+ }
1269
+ function getHydrationDirective(props) {
1270
+ if (props["client:load"] !== void 0) return { strategy: "load" };
1271
+ if (props["client:idle"] !== void 0) return { strategy: "idle" };
1272
+ if (props["client:visible"] !== void 0) return { strategy: "visible" };
1273
+ if (props["client:only"] !== void 0) return { strategy: "only" };
1274
+ if (props["client:media"] !== void 0) return {
1275
+ strategy: "media",
1276
+ media: props["client:media"]
1220
1277
  };
1221
- function getEvent(actionName, type) {
1222
- const name = `${actionName}.${type}`;
1223
- if (!events[name]) {
1224
- events[name] = createTopic({
1225
- namespace,
1226
- name
1227
- });
1228
- messages.push(events[name]);
1229
- }
1230
- return events[name];
1231
- }
1232
- Object.keys(actions).forEach((actionName) => {
1233
- onDispatching[actionName] = { subscribe: (fn) => {
1234
- return getEvent(actionName, "onDispatching").subscribe(function() {
1235
- fn.apply(this, arguments[0]);
1236
- });
1237
- } };
1238
- onDispatched[actionName] = { subscribe: (fn) => {
1239
- return getEvent(actionName, "onDispatched").subscribe(function() {
1240
- const msg = arguments[0];
1241
- const allArguments = [msg.result].concat(Array.from(msg.args));
1242
- fn.apply(this, allArguments);
1243
- });
1244
- } };
1245
- onFailure[actionName] = { subscribe: (fn) => {
1246
- return getEvent(actionName, "onFailure").subscribe(function() {
1247
- const msg = arguments[0];
1248
- const allArguments = [msg.reason].concat(Array.from(msg.args));
1249
- fn.apply(this, allArguments);
1250
- });
1251
- } };
1252
- result[actionName] = function() {
1253
- try {
1254
- const currentArguments = arguments;
1255
- getEvent(actionName, "onDispatching").publish(currentArguments);
1256
- const returnedResult = actions[actionName].apply(this, currentArguments);
1257
- if (Utils.isPromise(returnedResult)) returnedResult.then((result$1) => {
1258
- getEvent(actionName, "onDispatched").publish({
1259
- result: returnedResult,
1260
- args: currentArguments
1261
- });
1262
- });
1263
- else getEvent(actionName, "onDispatched").publish({
1264
- result: returnedResult,
1265
- args: currentArguments
1266
- });
1267
- return returnedResult;
1268
- } catch (err) {
1269
- console.error(err);
1270
- getEvent(actionName, "onFailure").publish({
1271
- reason: err,
1272
- args: arguments
1273
- });
1274
- }
1275
- };
1276
- });
1277
- return result;
1278
+ return null;
1278
1279
  }
1279
- function defineState(value, storeInstanceName, scope, messages) {
1280
- const state = signal(value);
1281
- const events = {};
1282
- const mutate = {};
1283
- function initProperty(key) {
1284
- scope.run(() => {
1285
- watch(() => state[key], (newValue) => {
1286
- triggerEvent(key, newValue);
1287
- }, {
1288
- deep: true,
1289
- immediate: true
1290
- });
1291
- });
1292
- mutate[key] = (val) => {
1293
- try {
1294
- let newValue;
1295
- if (typeof val === "function") newValue = val(state[key]);
1296
- else newValue = val;
1297
- state[key] = newValue;
1298
- } catch (err) {
1299
- console.error(err);
1300
- }
1301
- };
1302
- const eventKey = `onMutated${key.charAt(0).toUpperCase()}${key.slice(1)}`;
1303
- if (!events[eventKey]) {
1304
- const topic = createTopic({
1305
- namespace: `${storeInstanceName}.events`,
1306
- name: eventKey
1307
- });
1308
- events[eventKey] = topic;
1309
- messages.push(topic);
1310
- }
1311
- }
1312
- function triggerEvent(name, value$1) {
1313
- const keyString = name;
1314
- events[`onMutated${keyString.charAt(0).toUpperCase()}${keyString.slice(1)}`]?.publish(value$1);
1280
+ function hasClientDirective(props) {
1281
+ for (const key in props) if (key.startsWith("client:")) return true;
1282
+ return false;
1283
+ }
1284
+ function serializeProps(props) {
1285
+ const filtered = filterClientDirectives(props);
1286
+ const result = {};
1287
+ let hasProps = false;
1288
+ for (const key in filtered) {
1289
+ const value = filtered[key];
1290
+ if (key === "children" || key === "key" || key === "ref" || key === "slots") continue;
1291
+ if (typeof value === "function") continue;
1292
+ if (typeof value === "symbol") continue;
1293
+ if (value === void 0) continue;
1294
+ if (key.startsWith("on") && key.length > 2 && key[2] === key[2].toUpperCase()) continue;
1295
+ try {
1296
+ JSON.stringify(value);
1297
+ result[key] = value;
1298
+ hasProps = true;
1299
+ } catch {}
1315
1300
  }
1316
- if (value) Object.keys(value).forEach((key) => {
1317
- initProperty(key);
1318
- });
1319
- return {
1320
- state,
1321
- events,
1322
- mutate
1323
- };
1301
+ return hasProps ? result : void 0;
1324
1302
  }
1325
-
1326
- //#endregion
1327
- //#region ../runtime-core/src/renderer.ts
1328
- /**
1329
- * Check if a vnode type is a component (has __setup)
1330
- */
1331
- function isComponent(type) {
1332
- return typeof type === "function" && "__setup" in type;
1303
+ function createEmit(reactiveProps) {
1304
+ return (event, ...args) => {
1305
+ const eventName = `on${event[0].toUpperCase() + event.slice(1)}`;
1306
+ const handler = ("value" in reactiveProps ? reactiveProps.value : reactiveProps)?.[eventName];
1307
+ if (handler && typeof handler === "function") handler(...args);
1308
+ };
1333
1309
  }
1334
1310
  function createRenderer(options) {
1335
1311
  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;
1336
1312
  let currentAppContext = null;
1337
- function render$1(element, container, appContext) {
1313
+ function render(element, container, appContext) {
1338
1314
  if (appContext) currentAppContext = appContext;
1339
1315
  const oldVNode = container._vnode;
1340
1316
  let vnode = null;
@@ -1363,7 +1339,72 @@ function createRenderer(options) {
1363
1339
  container._vnode = null;
1364
1340
  }
1365
1341
  }
1366
- function mount(vnode, container, before = null) {
1342
+ const svgTags = new Set([
1343
+ "svg",
1344
+ "animate",
1345
+ "animateMotion",
1346
+ "animateTransform",
1347
+ "circle",
1348
+ "clipPath",
1349
+ "defs",
1350
+ "desc",
1351
+ "ellipse",
1352
+ "feBlend",
1353
+ "feColorMatrix",
1354
+ "feComponentTransfer",
1355
+ "feComposite",
1356
+ "feConvolveMatrix",
1357
+ "feDiffuseLighting",
1358
+ "feDisplacementMap",
1359
+ "feDistantLight",
1360
+ "feDropShadow",
1361
+ "feFlood",
1362
+ "feFuncA",
1363
+ "feFuncB",
1364
+ "feFuncG",
1365
+ "feFuncR",
1366
+ "feGaussianBlur",
1367
+ "feImage",
1368
+ "feMerge",
1369
+ "feMergeNode",
1370
+ "feMorphology",
1371
+ "feOffset",
1372
+ "fePointLight",
1373
+ "feSpecularLighting",
1374
+ "feSpotLight",
1375
+ "feTile",
1376
+ "feTurbulence",
1377
+ "filter",
1378
+ "foreignObject",
1379
+ "g",
1380
+ "image",
1381
+ "line",
1382
+ "linearGradient",
1383
+ "marker",
1384
+ "mask",
1385
+ "metadata",
1386
+ "mpath",
1387
+ "path",
1388
+ "pattern",
1389
+ "polygon",
1390
+ "polyline",
1391
+ "radialGradient",
1392
+ "rect",
1393
+ "set",
1394
+ "stop",
1395
+ "switch",
1396
+ "symbol",
1397
+ "text",
1398
+ "textPath",
1399
+ "title",
1400
+ "tspan",
1401
+ "use",
1402
+ "view"
1403
+ ]);
1404
+ function isSvgTag(tag) {
1405
+ return svgTags.has(tag);
1406
+ }
1407
+ function mount(vnode, container, before = null, parentIsSVG = false) {
1367
1408
  if (vnode == null || vnode === false || vnode === true) return;
1368
1409
  if (vnode.type === Text) {
1369
1410
  const node = hostCreateText(String(vnode.text));
@@ -1376,26 +1417,29 @@ function createRenderer(options) {
1376
1417
  const anchor = hostCreateComment("");
1377
1418
  vnode.dom = anchor;
1378
1419
  hostInsert(anchor, container, before);
1379
- if (vnode.children) vnode.children.forEach((child) => mount(child, container, anchor));
1420
+ if (vnode.children) vnode.children.forEach((child) => mount(child, container, anchor, parentIsSVG));
1380
1421
  return;
1381
1422
  }
1382
1423
  if (isComponent(vnode.type)) {
1383
1424
  mountComponent(vnode, container, before, vnode.type.__setup);
1384
1425
  return;
1385
1426
  }
1386
- const element = hostCreateElement(vnode.type);
1427
+ const tag = vnode.type;
1428
+ const isSVG = tag === "svg" || parentIsSVG && tag !== "foreignObject";
1429
+ const element = hostCreateElement(tag, isSVG);
1387
1430
  vnode.dom = element;
1388
1431
  element.__vnode = vnode;
1389
1432
  if (vnode.props) {
1390
- for (const key in vnode.props) if (key !== "children" && key !== "key" && key !== "ref") hostPatchProp(element, key, null, vnode.props[key]);
1391
- if (vnode.props.ref) {
1433
+ for (const key in vnode.props) if (key !== "children" && key !== "key" && key !== "ref") hostPatchProp(element, key, null, vnode.props[key], isSVG);
1434
+ if (vnode.props.ref) untrack(() => {
1392
1435
  if (typeof vnode.props.ref === "function") vnode.props.ref(element);
1393
1436
  else if (typeof vnode.props.ref === "object") vnode.props.ref.current = element;
1394
- }
1437
+ });
1395
1438
  }
1439
+ const childIsSVG = isSVG && tag !== "foreignObject";
1396
1440
  if (vnode.children) vnode.children.forEach((child) => {
1397
1441
  child.parent = vnode;
1398
- mount(child, element);
1442
+ mount(child, element, null, childIsSVG);
1399
1443
  });
1400
1444
  hostInsert(element, container, before);
1401
1445
  }
@@ -1407,10 +1451,10 @@ function createRenderer(options) {
1407
1451
  const subTree = internalVNode._subTree;
1408
1452
  if (subTree) unmount(subTree, container);
1409
1453
  if (vnode.dom) hostRemove(vnode.dom);
1410
- if (vnode.props?.ref) {
1454
+ if (vnode.props?.ref) untrack(() => {
1411
1455
  if (typeof vnode.props.ref === "function") vnode.props.ref(null);
1412
1456
  else if (typeof vnode.props.ref === "object") vnode.props.ref.current = null;
1413
- }
1457
+ });
1414
1458
  return;
1415
1459
  }
1416
1460
  if (vnode.type === Fragment) {
@@ -1418,10 +1462,10 @@ function createRenderer(options) {
1418
1462
  if (vnode.dom) hostRemove(vnode.dom);
1419
1463
  return;
1420
1464
  }
1421
- if (vnode.props?.ref) {
1465
+ if (vnode.props?.ref) untrack(() => {
1422
1466
  if (typeof vnode.props.ref === "function") vnode.props.ref(null);
1423
1467
  else if (vnode.props.ref && typeof vnode.props.ref === "object") vnode.props.ref.current = null;
1424
- }
1468
+ });
1425
1469
  if (vnode.children && vnode.children.length > 0) vnode.children.forEach((child) => unmount(child, vnode.dom));
1426
1470
  if (vnode.dom) hostRemove(vnode.dom);
1427
1471
  }
@@ -1429,7 +1473,7 @@ function createRenderer(options) {
1429
1473
  if (oldVNode === newVNode) return;
1430
1474
  if (!isSameVNode(oldVNode, newVNode)) {
1431
1475
  const parent = hostParentNode(oldVNode.dom) || container;
1432
- const nextSibling = hostNextSibling(oldVNode.dom);
1476
+ const nextSibling = oldVNode.dom ? hostNextSibling(oldVNode.dom) : null;
1433
1477
  unmount(oldVNode, parent);
1434
1478
  mount(newVNode, parent, nextSibling);
1435
1479
  return;
@@ -1444,12 +1488,25 @@ function createRenderer(options) {
1444
1488
  const props = oldInternal._componentProps;
1445
1489
  newInternal._componentProps = props;
1446
1490
  if (props) {
1447
- const newProps$1 = newVNode.props || {};
1491
+ const newProps = newVNode.props || {};
1492
+ const newModels = newVNode.props?.$models || {};
1448
1493
  untrack(() => {
1449
- for (const key in newProps$1) if (key !== "children" && key !== "key" && key !== "ref") {
1450
- if (props[key] !== newProps$1[key]) props[key] = newProps$1[key];
1494
+ for (const key in newProps) if (key !== "children" && key !== "key" && key !== "ref" && key !== "$models") {
1495
+ if (props[key] !== newProps[key]) props[key] = newProps[key];
1496
+ }
1497
+ for (const modelKey in newModels) {
1498
+ const newModel = newModels[modelKey];
1499
+ const oldModel = props[modelKey];
1500
+ if (isModel(newModel)) {
1501
+ if (isModel(oldModel)) {
1502
+ const [newObj, newKey] = newModel.binding;
1503
+ const [oldObj, oldKey] = oldModel.binding;
1504
+ if (newObj === oldObj && newKey === oldKey) continue;
1505
+ }
1506
+ props[modelKey] = newModel;
1507
+ }
1451
1508
  }
1452
- for (const key in props) if (!(key in newProps$1) && key !== "children" && key !== "key" && key !== "ref") delete props[key];
1509
+ for (const key in props) if (!(key in newProps) && !(key in newModels) && key !== "children" && key !== "key" && key !== "ref" && key !== "$models") delete props[key];
1453
1510
  });
1454
1511
  }
1455
1512
  const slotsRef = oldInternal._slots;
@@ -1477,27 +1534,43 @@ function createRenderer(options) {
1477
1534
  return;
1478
1535
  }
1479
1536
  if (newVNode.type === Fragment) {
1480
- patchChildren(oldVNode, newVNode, container);
1537
+ patchChildren(oldVNode, newVNode, container, false);
1481
1538
  return;
1482
1539
  }
1483
1540
  const element = newVNode.dom = oldVNode.dom;
1541
+ if (!element) {
1542
+ mount(newVNode, container);
1543
+ return;
1544
+ }
1545
+ const tag = newVNode.type;
1546
+ const isSVG = tag === "svg" || isSvgTag(tag);
1484
1547
  const oldProps = oldVNode.props || {};
1485
1548
  const newProps = newVNode.props || {};
1486
- for (const key in oldProps) if (!(key in newProps) && key !== "children" && key !== "key" && key !== "ref") hostPatchProp(element, key, oldProps[key], null);
1549
+ for (const key in oldProps) if (!(key in newProps) && key !== "children" && key !== "key" && key !== "ref") hostPatchProp(element, key, oldProps[key], null, isSVG);
1487
1550
  for (const key in newProps) {
1488
1551
  const oldValue = oldProps[key];
1489
1552
  const newValue = newProps[key];
1490
- if (key !== "children" && key !== "key" && key !== "ref" && oldValue !== newValue) hostPatchProp(element, key, oldValue, newValue);
1553
+ if (key !== "children" && key !== "key" && key !== "ref" && oldValue !== newValue) hostPatchProp(element, key, oldValue, newValue, isSVG);
1491
1554
  }
1492
- patchChildren(oldVNode, newVNode, element);
1555
+ patchChildren(oldVNode, newVNode, element, isSVG && tag !== "foreignObject");
1493
1556
  }
1494
- function patchChildren(oldVNode, newVNode, container) {
1557
+ function patchChildren(oldVNode, newVNode, container, parentIsSVG = false) {
1495
1558
  const oldChildren = oldVNode.children;
1496
1559
  const newChildren = newVNode.children;
1497
1560
  newChildren.forEach((c) => c.parent = newVNode);
1498
- reconcileChildrenArray(container, oldChildren, newChildren);
1561
+ reconcileChildrenArray(container, oldChildren, newChildren, parentIsSVG);
1499
1562
  }
1500
- function reconcileChildrenArray(parent, oldChildren, newChildren) {
1563
+ function checkDuplicateKeys(children) {
1564
+ if (process.env.NODE_ENV === "production") return;
1565
+ const seenKeys = /* @__PURE__ */ new Set();
1566
+ for (const child of children) if (child?.key != null) {
1567
+ const keyStr = String(child.key);
1568
+ if (seenKeys.has(keyStr)) console.warn(`[SignalX] Duplicate key "${child.key}" detected in list. Keys should be unique among siblings to ensure correct reconciliation. This may cause unexpected behavior when items are reordered, added, or removed.`);
1569
+ seenKeys.add(keyStr);
1570
+ }
1571
+ }
1572
+ function reconcileChildrenArray(parent, oldChildren, newChildren, parentIsSVG = false) {
1573
+ if (process.env.NODE_ENV !== "production") checkDuplicateKeys(newChildren);
1501
1574
  let oldStartIdx = 0;
1502
1575
  let oldEndIdx = oldChildren.length - 1;
1503
1576
  let oldStartVNode = oldChildren[0];
@@ -1539,13 +1612,13 @@ function createRenderer(options) {
1539
1612
  patch(vnodeToMove, newStartVNode, parent);
1540
1613
  oldChildren[idxInOld] = void 0;
1541
1614
  if (vnodeToMove.dom && oldStartVNode.dom) hostInsert(vnodeToMove.dom, parent, oldStartVNode.dom);
1542
- } else mount(newStartVNode, parent, oldStartVNode.dom);
1615
+ } else mount(newStartVNode, parent, oldStartVNode.dom, parentIsSVG);
1543
1616
  newStartVNode = newChildren[++newStartIdx];
1544
1617
  }
1545
1618
  if (oldStartIdx > oldEndIdx) {
1546
1619
  if (newStartIdx <= newEndIdx) {
1547
1620
  const anchor = newChildren[newEndIdx + 1] == null ? null : newChildren[newEndIdx + 1].dom;
1548
- for (let i = newStartIdx; i <= newEndIdx; i++) mount(newChildren[i], parent, anchor);
1621
+ for (let i = newStartIdx; i <= newEndIdx; i++) mount(newChildren[i], parent, anchor, parentIsSVG);
1549
1622
  }
1550
1623
  } else if (newStartIdx > newEndIdx) {
1551
1624
  for (let i = oldStartIdx; i <= oldEndIdx; i++) if (oldChildren[i]) unmount(oldChildren[i], parent);
@@ -1562,7 +1635,11 @@ function createRenderer(options) {
1562
1635
  const map = /* @__PURE__ */ new Map();
1563
1636
  for (let i = beginIdx; i <= endIdx; i++) {
1564
1637
  const key = children[i]?.key;
1565
- if (key != null) map.set(String(key), i);
1638
+ if (key != null) {
1639
+ const keyStr = String(key);
1640
+ if (process.env.NODE_ENV !== "production" && map.has(keyStr)) console.warn(`[SignalX] Duplicate key "${key}" detected in list. Keys should be unique among siblings to ensure correct reconciliation. This may cause unexpected behavior when items are reordered, added, or removed.`);
1641
+ map.set(keyStr, i);
1642
+ }
1566
1643
  }
1567
1644
  return map;
1568
1645
  }
@@ -1577,14 +1654,21 @@ function createRenderer(options) {
1577
1654
  hostInsert(anchor, container, before);
1578
1655
  let exposed = null;
1579
1656
  let exposeCalled = false;
1580
- const { children, slots: slotsFromProps, ...propsData } = vnode.props || {};
1581
- const reactiveProps = signal(propsData);
1657
+ const { children, slots: slotsFromProps, $models: modelsData, ...propsData } = vnode.props || {};
1658
+ const propsWithModels = { ...propsData };
1659
+ if (modelsData) for (const modelKey in modelsData) {
1660
+ const modelValue = modelsData[modelKey];
1661
+ if (isModel(modelValue)) propsWithModels[modelKey] = modelValue;
1662
+ }
1663
+ const reactiveProps = signal(propsWithModels);
1582
1664
  const internalVNode = vnode;
1583
1665
  internalVNode._componentProps = reactiveProps;
1584
1666
  const slots = createSlots(children, slotsFromProps);
1585
1667
  internalVNode._slots = slots;
1668
+ const createdHooks = [];
1586
1669
  const mountHooks = [];
1587
- const cleanupHooks = [];
1670
+ const updatedHooks = [];
1671
+ const unmountHooks = [];
1588
1672
  const parentInstance = getCurrentInstance();
1589
1673
  const componentName = vnode.type.__name;
1590
1674
  const ctx = {
@@ -1592,16 +1676,19 @@ function createRenderer(options) {
1592
1676
  signal,
1593
1677
  props: createPropsAccessor(reactiveProps),
1594
1678
  slots,
1595
- emit: (event, ...args) => {
1596
- const handler = reactiveProps[`on${event[0].toUpperCase() + event.slice(1)}`];
1597
- if (handler && typeof handler === "function") handler(...args);
1598
- },
1679
+ emit: createEmit(reactiveProps),
1599
1680
  parent: parentInstance,
1600
- onMount: (fn) => {
1681
+ onMounted: (fn) => {
1601
1682
  mountHooks.push(fn);
1602
1683
  },
1603
- onCleanup: (fn) => {
1604
- cleanupHooks.push(fn);
1684
+ onUnmounted: (fn) => {
1685
+ unmountHooks.push(fn);
1686
+ },
1687
+ onCreated: (fn) => {
1688
+ createdHooks.push(fn);
1689
+ },
1690
+ onUpdated: (fn) => {
1691
+ updatedHooks.push(fn);
1605
1692
  },
1606
1693
  expose: (exposedValue) => {
1607
1694
  exposed = exposedValue;
@@ -1612,7 +1699,7 @@ function createRenderer(options) {
1612
1699
  };
1613
1700
  applyContextExtensions(ctx);
1614
1701
  ctx.__name = componentName;
1615
- if (currentAppContext) ctx._appContext = currentAppContext;
1702
+ if (!parentInstance && currentAppContext) provideAppContext(ctx, currentAppContext);
1616
1703
  const componentInstance = {
1617
1704
  name: componentName,
1618
1705
  ctx,
@@ -1622,9 +1709,10 @@ function createRenderer(options) {
1622
1709
  let renderFn;
1623
1710
  try {
1624
1711
  const setupResult = setup(ctx);
1625
- 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.`);
1712
+ 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 onMounted.`);
1626
1713
  renderFn = setupResult;
1627
1714
  notifyComponentCreated(currentAppContext, componentInstance);
1715
+ createdHooks.forEach((hook) => hook());
1628
1716
  } catch (err) {
1629
1717
  if (!handleComponentError(currentAppContext, err, componentInstance, "setup")) throw err;
1630
1718
  } finally {
@@ -1632,8 +1720,10 @@ function createRenderer(options) {
1632
1720
  }
1633
1721
  if (vnode.props?.ref) {
1634
1722
  const refValue = exposeCalled ? exposed : null;
1635
- if (typeof vnode.props.ref === "function") vnode.props.ref(refValue);
1636
- else if (vnode.props.ref && typeof vnode.props.ref === "object") vnode.props.ref.current = refValue;
1723
+ untrack(() => {
1724
+ if (typeof vnode.props.ref === "function") vnode.props.ref(refValue);
1725
+ else if (vnode.props.ref && typeof vnode.props.ref === "object") vnode.props.ref.current = refValue;
1726
+ });
1637
1727
  }
1638
1728
  if (renderFn) {
1639
1729
  ctx.renderFn = renderFn;
@@ -1647,6 +1737,7 @@ function createRenderer(options) {
1647
1737
  if (prevSubTree) {
1648
1738
  patch(prevSubTree, subTree, container);
1649
1739
  notifyComponentUpdated(currentAppContext, componentInstance);
1740
+ updatedHooks.forEach((hook) => hook());
1650
1741
  } else mount(subTree, container, anchor);
1651
1742
  internalVNode._subTree = subTree;
1652
1743
  } catch (err) {
@@ -1665,34 +1756,18 @@ function createRenderer(options) {
1665
1756
  notifyComponentMounted(currentAppContext, componentInstance);
1666
1757
  vnode.cleanup = () => {
1667
1758
  notifyComponentUnmounted(currentAppContext, componentInstance);
1668
- cleanupHooks.forEach((hook) => hook(mountCtx));
1759
+ unmountHooks.forEach((hook) => hook(mountCtx));
1669
1760
  };
1670
1761
  }
1671
1762
  return {
1672
- render: render$1,
1763
+ render,
1673
1764
  patch,
1674
1765
  mount,
1675
1766
  unmount,
1676
- mountComponent,
1677
- createApp: (rootComponent) => {
1678
- return { mount(selectorOrContainer) {
1679
- let container = null;
1680
- if (typeof selectorOrContainer === "string") {
1681
- if (options.querySelector) container = options.querySelector(selectorOrContainer);
1682
- } else container = selectorOrContainer;
1683
- if (!container) {
1684
- console.warn(`Container not found: ${selectorOrContainer}`);
1685
- return;
1686
- }
1687
- render$1(rootComponent, container);
1688
- } };
1689
- }
1767
+ mountComponent
1690
1768
  };
1691
1769
  }
1692
-
1693
- //#endregion
1694
- //#region ../runtime-terminal/src/focus.ts
1695
- const focusableIds = /* @__PURE__ */ new Set();
1770
+ var focusableIds = /* @__PURE__ */ new Set();
1696
1771
  const focusState = signal({ activeId: null });
1697
1772
  function registerFocusable(id) {
1698
1773
  focusableIds.add(id);
@@ -1718,9 +1793,6 @@ function focusPrev() {
1718
1793
  const ids = Array.from(focusableIds);
1719
1794
  focusState.activeId = ids[((focusState.activeId ? ids.indexOf(focusState.activeId) : -1) - 1 + ids.length) % ids.length];
1720
1795
  }
1721
-
1722
- //#endregion
1723
- //#region ../runtime-terminal/src/utils.ts
1724
1796
  function getColorCode(color) {
1725
1797
  switch (color) {
1726
1798
  case "red": return "\x1B[31m";
@@ -1748,316 +1820,62 @@ function getBackgroundColorCode(color) {
1748
1820
  function stripAnsi(str) {
1749
1821
  return str.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "");
1750
1822
  }
1751
-
1752
- //#endregion
1753
- //#region ../runtime-core/dist/index.js
1754
- let platformSyncProcessor = null;
1755
- /**
1756
- * Get the current platform sync processor (for internal use).
1757
- */
1758
- function getPlatformSyncProcessor$1() {
1759
- return platformSyncProcessor;
1760
- }
1761
- const plugins = [];
1762
- /**
1763
- * Get all registered plugins (internal use)
1764
- */
1765
- function getComponentPlugins$1() {
1766
- return plugins;
1767
- }
1768
- const componentRegistry = /* @__PURE__ */ new Map();
1769
- /**
1770
- * Define a component. Returns a JSX factory function.
1771
- *
1772
- * @param setup - Setup function that receives context and returns a render function
1773
- * @param options - Optional configuration (e.g., name for DevTools)
1774
- *
1775
- * @example
1776
- * ```tsx
1777
- * type CardProps = DefineProp<"title", string> & DefineSlot<"header">;
1778
- *
1779
- * export const Card = defineComponent<CardProps>((ctx) => {
1780
- * const { title } = ctx.props;
1781
- * const { slots } = ctx;
1782
- *
1783
- * return () => (
1784
- * <div class="card">
1785
- * {slots.header?.() ?? <h2>{title}</h2>}
1786
- * {slots.default()}
1787
- * </div>
1788
- * );
1789
- * });
1790
- * ```
1791
- */
1792
- function defineComponent$1(setup, options) {
1793
- const factory = function(props) {
1794
- return {
1795
- type: factory,
1796
- props: props || {},
1797
- key: props?.key || null,
1798
- children: [],
1799
- dom: null
1800
- };
1801
- };
1802
- factory.__setup = setup;
1803
- factory.__name = options?.name;
1804
- factory.__props = null;
1805
- factory.__events = null;
1806
- factory.__ref = null;
1807
- factory.__slots = null;
1808
- componentRegistry.set(factory, {
1809
- name: options?.name,
1810
- setup
1811
- });
1812
- getComponentPlugins$1().forEach((p) => p.onDefine?.(options?.name, factory, setup));
1813
- return factory;
1814
- }
1815
- const Fragment$1 = Symbol.for("sigx.Fragment");
1816
- const Text$1 = Symbol.for("sigx.Text");
1817
- function normalizeChildren(children) {
1818
- if (children == null || children === false || children === true) return [];
1819
- if (Array.isArray(children)) return children.flatMap((c) => normalizeChildren(c));
1820
- if (typeof children === "string" || typeof children === "number") return [{
1821
- type: Text$1,
1822
- props: {},
1823
- key: null,
1824
- children: [],
1825
- dom: null,
1826
- text: children
1827
- }];
1828
- if (children.type) return [children];
1829
- return [];
1830
- }
1831
- /**
1832
- * Check if a type is a sigx component (has __setup)
1833
- */
1834
- function isComponent$1(type) {
1835
- return typeof type === "function" && "__setup" in type;
1836
- }
1837
- /**
1838
- * Create a JSX element - this is the core function called by TSX transpilation
1839
- */
1840
- function jsx$1(type, props, key) {
1841
- const processedProps = { ...props || {} };
1842
- if (props) {
1843
- for (const propKey in props) if (propKey === "sync") {
1844
- let syncBinding = props[propKey];
1845
- if (typeof syncBinding === "function") {
1846
- const detected = detectAccess(syncBinding);
1847
- if (detected) syncBinding = detected;
1848
- }
1849
- if (Array.isArray(syncBinding) && syncBinding.length === 2) {
1850
- const [stateObj, key$1] = syncBinding;
1851
- let handled = false;
1852
- const platformProcessor = getPlatformSyncProcessor$1();
1853
- if (typeof type === "string" && platformProcessor) handled = platformProcessor(type, processedProps, [stateObj, key$1], props);
1854
- if (!handled) {
1855
- processedProps.value = stateObj[key$1];
1856
- const existingHandler = processedProps["onUpdate:value"];
1857
- processedProps["onUpdate:value"] = (v) => {
1858
- stateObj[key$1] = v;
1859
- if (existingHandler) existingHandler(v);
1860
- };
1861
- }
1862
- delete processedProps.sync;
1863
- }
1864
- } else if (propKey.startsWith("sync:")) {
1865
- const syncBinding = props[propKey];
1866
- if (Array.isArray(syncBinding) && syncBinding.length === 2) {
1867
- const [stateObj, key$1] = syncBinding;
1868
- const name = propKey.slice(5);
1869
- processedProps[name] = stateObj[key$1];
1870
- const eventName = `onUpdate:${name}`;
1871
- const existingHandler = processedProps[eventName];
1872
- processedProps[eventName] = (v) => {
1873
- stateObj[key$1] = v;
1874
- if (existingHandler) existingHandler(v);
1875
- };
1876
- delete processedProps[propKey];
1877
- }
1878
- }
1879
- }
1880
- if (isComponent$1(type)) {
1881
- const { children: children$1, ...rest$1 } = processedProps;
1882
- return {
1883
- type,
1884
- props: {
1885
- ...rest$1,
1886
- children: children$1
1887
- },
1888
- key: key || rest$1.key || null,
1889
- children: [],
1890
- dom: null
1891
- };
1892
- }
1893
- if (typeof type === "function" && type !== Fragment$1) return type(processedProps);
1894
- const { children, ...rest } = processedProps;
1895
- return {
1896
- type,
1897
- props: rest,
1898
- key: key || rest.key || null,
1899
- children: normalizeChildren(children),
1900
- dom: null
1901
- };
1902
- }
1903
- /**
1904
- * JSX Factory for fragments
1905
- */
1906
- function jsxs$1(type, props, key) {
1907
- return jsx$1(type, props, key);
1908
- }
1909
- /**
1910
- * Lazy loading utilities for sigx components.
1911
- *
1912
- * Provides runtime-only lazy loading with no build dependencies.
1913
- * Works with any bundler that supports dynamic import().
1914
- */
1915
- let currentSuspenseBoundary = null;
1916
- /**
1917
- * Register a promise with the current Suspense boundary
1918
- * @internal
1919
- */
1920
- function registerPendingPromise$1(promise) {
1921
- const boundary = currentSuspenseBoundary;
1922
- if (boundary) {
1923
- boundary.pending.add(promise);
1924
- promise.finally(() => {
1925
- boundary.pending.delete(promise);
1926
- if (boundary.pending.size === 0) boundary.onResolve();
1927
- });
1928
- return true;
1929
- }
1930
- return false;
1931
- }
1932
- /**
1933
- * Suspense boundary component for handling async loading states.
1934
- *
1935
- * Wraps lazy-loaded components and shows a fallback while they load.
1936
- *
1937
- * @example
1938
- * ```tsx
1939
- * import { lazy, Suspense } from 'sigx';
1940
- *
1941
- * const LazyDashboard = lazy(() => import('./Dashboard'));
1942
- *
1943
- * // Basic usage
1944
- * <Suspense fallback={<div>Loading...</div>}>
1945
- * <LazyDashboard />
1946
- * </Suspense>
1947
- *
1948
- * // With spinner component
1949
- * <Suspense fallback={<Spinner size="large" />}>
1950
- * <LazyDashboard />
1951
- * <LazyCharts />
1952
- * </Suspense>
1953
- * ```
1954
- */
1955
- const Suspense$1 = defineComponent$1((ctx) => {
1956
- const { props, slots } = ctx;
1957
- const state = ctx.signal({
1958
- isReady: false,
1959
- pendingCount: 0
1960
- });
1961
- const boundary = {
1962
- pending: /* @__PURE__ */ new Set(),
1963
- onResolve: () => {
1964
- state.pendingCount = boundary.pending.size;
1965
- if (boundary.pending.size === 0) state.isReady = true;
1966
- }
1967
- };
1968
- ctx.onMount(() => {
1969
- if (boundary.pending.size === 0) state.isReady = true;
1970
- });
1971
- return () => {
1972
- state.isReady;
1973
- state.pendingCount;
1974
- const prevBoundary = currentSuspenseBoundary;
1975
- currentSuspenseBoundary = boundary;
1976
- try {
1977
- const children = slots.default();
1978
- if (boundary.pending.size > 0) {
1979
- const fallback = props.fallback;
1980
- if (typeof fallback === "function") return fallback();
1981
- return fallback ?? null;
1982
- }
1983
- if (Array.isArray(children)) {
1984
- const filtered = children.filter((c) => c != null && c !== false && c !== true);
1985
- if (filtered.length === 0) return null;
1986
- if (filtered.length === 1) return filtered[0];
1987
- return filtered;
1988
- }
1989
- return children;
1990
- } catch (err) {
1991
- if (err instanceof Promise) {
1992
- registerPendingPromise$1(err);
1993
- const fallback = props.fallback;
1994
- if (typeof fallback === "function") return fallback();
1995
- return fallback ?? null;
1996
- }
1997
- throw err;
1998
- } finally {
1999
- currentSuspenseBoundary = prevBoundary;
2000
- }
2001
- };
2002
- }, { name: "Suspense" });
2003
-
2004
- //#endregion
2005
- //#region ../runtime-terminal/src/components/Input.tsx
2006
- /** @jsxImportSource @sigx/runtime-core */
2007
- const Input = defineComponent(({ props, emit }) => {
1823
+ const Input = component(({ props, emit }) => {
2008
1824
  const id = Math.random().toString(36).slice(2);
1825
+ let isReady = false;
2009
1826
  const isFocused = () => focusState.activeId === id;
1827
+ const getValue = () => props.model?.value || "";
2010
1828
  const handleKey = (key) => {
2011
1829
  if (!isFocused()) return;
1830
+ if (!isReady) return;
2012
1831
  if (key === "\r") {
2013
- emit("submit", props.value || "");
1832
+ emit("submit", getValue());
2014
1833
  return;
2015
1834
  }
2016
1835
  if (key === "\n") return;
2017
1836
  if (key === "" || key === "\b") {
2018
- const val = props.value || "";
1837
+ const val = getValue();
2019
1838
  if (val.length > 0) {
2020
- const newValue$1 = val.slice(0, -1);
2021
- emit("update:value", newValue$1);
2022
- emit("input", newValue$1);
1839
+ const newValue = val.slice(0, -1);
1840
+ if (props.model) props.model.value = newValue;
1841
+ emit("input", newValue);
2023
1842
  }
2024
1843
  return;
2025
1844
  }
2026
1845
  if (key.length > 1) return;
2027
- const newValue = (props.value || "") + key;
2028
- emit("update:value", newValue);
1846
+ const newValue = getValue() + key;
1847
+ if (props.model) props.model.value = newValue;
2029
1848
  emit("input", newValue);
2030
1849
  };
2031
1850
  let keyCleanup = null;
2032
- onMount(() => {
1851
+ onMounted(() => {
2033
1852
  registerFocusable(id);
2034
1853
  if (props.autofocus) focus(id);
2035
1854
  keyCleanup = onKey(handleKey);
1855
+ setTimeout(() => {
1856
+ isReady = true;
1857
+ }, 50);
2036
1858
  });
2037
- onCleanup(() => {
1859
+ onUnmounted(() => {
2038
1860
  if (keyCleanup) keyCleanup();
2039
1861
  unregisterFocusable(id);
2040
1862
  });
2041
1863
  return () => {
2042
- const val = (props.value || "").replace(/[\r\n]+/g, " ");
1864
+ const val = getValue().replace(/[\r\n]+/g, " ");
2043
1865
  const placeholder = (props.placeholder || "").replace(/[\r\n]+/g, " ");
2044
1866
  const showCursor = isFocused();
2045
- return /* @__PURE__ */ jsxs$1("box", {
1867
+ return /* @__PURE__ */ jsxs("box", {
2046
1868
  border: "single",
2047
1869
  borderColor: showCursor ? "green" : "white",
2048
1870
  label: props.label,
2049
- children: [/* @__PURE__ */ jsx$1("text", { children: val || placeholder }), showCursor && /* @__PURE__ */ jsx$1("text", {
1871
+ children: [/* @__PURE__ */ jsx("text", { children: val || placeholder }), showCursor && /* @__PURE__ */ jsx("text", {
2050
1872
  color: "cyan",
2051
1873
  children: "_"
2052
1874
  })]
2053
1875
  });
2054
1876
  };
2055
1877
  }, { name: "Input" });
2056
-
2057
- //#endregion
2058
- //#region ../runtime-terminal/src/components/ProgressBar.tsx
2059
- /** @jsxImportSource @sigx/runtime-core */
2060
- const ProgressBar = defineComponent(({ props }) => {
1878
+ const ProgressBar = component(({ props }) => {
2061
1879
  return () => {
2062
1880
  const value = props.value || 0;
2063
1881
  const max = props.max || 100;
@@ -2070,14 +1888,10 @@ const ProgressBar = defineComponent(({ props }) => {
2070
1888
  const percentage = Math.min(Math.max(value / max, 0), 1);
2071
1889
  const filledLen = Math.round(width * percentage);
2072
1890
  const emptyLen = width - filledLen;
2073
- return /* @__PURE__ */ jsx$1("box", { children: /* @__PURE__ */ jsx$1("text", { children: colorCode + barChar.repeat(filledLen) + emptyChar.repeat(emptyLen) + reset + ` ${Math.round(percentage * 100)}%` }) });
1891
+ return /* @__PURE__ */ jsx("box", { children: /* @__PURE__ */ jsx("text", { children: colorCode + barChar.repeat(filledLen) + emptyChar.repeat(emptyLen) + reset + ` ${Math.round(percentage * 100)}%` }) });
2074
1892
  };
2075
1893
  }, { name: "ProgressBar" });
2076
-
2077
- //#endregion
2078
- //#region ../runtime-terminal/src/components/Button.tsx
2079
- /** @jsxImportSource @sigx/runtime-core */
2080
- const Button = defineComponent(({ props, emit }) => {
1894
+ const Button = component(({ props, emit }) => {
2081
1895
  const id = Math.random().toString(36).slice(2);
2082
1896
  const isFocused = () => focusState.activeId === id;
2083
1897
  const pressed = signal({ value: false });
@@ -2095,11 +1909,11 @@ const Button = defineComponent(({ props, emit }) => {
2095
1909
  };
2096
1910
  let keyCleanup = null;
2097
1911
  let pressTimer = null;
2098
- onMount(() => {
1912
+ onMounted(() => {
2099
1913
  registerFocusable(id);
2100
1914
  keyCleanup = onKey(handleKey);
2101
1915
  });
2102
- onCleanup(() => {
1916
+ onUnmounted(() => {
2103
1917
  if (keyCleanup) keyCleanup();
2104
1918
  unregisterFocusable(id);
2105
1919
  if (pressTimer) clearTimeout(pressTimer);
@@ -2108,42 +1922,38 @@ const Button = defineComponent(({ props, emit }) => {
2108
1922
  const focused = isFocused();
2109
1923
  const label = props.label || "Button";
2110
1924
  const isPressed = pressed.value;
2111
- return /* @__PURE__ */ jsx$1("box", {
1925
+ return /* @__PURE__ */ jsx("box", {
2112
1926
  border: "single",
2113
1927
  borderColor: isPressed ? "yellow" : focused ? "green" : "white",
2114
1928
  backgroundColor: isPressed ? "red" : focused ? "blue" : void 0,
2115
1929
  dropShadow: props.dropShadow,
2116
- children: /* @__PURE__ */ jsx$1("text", {
1930
+ children: /* @__PURE__ */ jsx("text", {
2117
1931
  color: focused ? "white" : void 0,
2118
1932
  children: label
2119
1933
  })
2120
1934
  });
2121
1935
  };
2122
1936
  }, { name: "Button" });
2123
-
2124
- //#endregion
2125
- //#region ../runtime-terminal/src/components/Checkbox.tsx
2126
- /** @jsxImportSource @sigx/runtime-core */
2127
- const Checkbox = defineComponent(({ props, emit }) => {
1937
+ const Checkbox = component(({ props, emit }) => {
2128
1938
  const id = Math.random().toString(36).slice(2);
2129
1939
  const isFocused = () => focusState.activeId === id;
2130
- const checked = () => !!props.value;
1940
+ const checked = () => !!props.model?.value;
2131
1941
  const handleKey = (key) => {
2132
1942
  if (!isFocused()) return;
2133
1943
  if (props.disabled) return;
2134
1944
  if (key === "\r" || key === " ") {
2135
1945
  const next = !checked();
2136
- emit("update:value", next);
1946
+ if (props.model) props.model.value = next;
2137
1947
  emit("change", next);
2138
1948
  }
2139
1949
  };
2140
1950
  let keyCleanup = null;
2141
- onMount(() => {
1951
+ onMounted(() => {
2142
1952
  registerFocusable(id);
2143
1953
  if (props.autofocus) focus(id);
2144
1954
  keyCleanup = onKey(handleKey);
2145
1955
  });
2146
- onCleanup(() => {
1956
+ onUnmounted(() => {
2147
1957
  if (keyCleanup) keyCleanup();
2148
1958
  unregisterFocusable(id);
2149
1959
  });
@@ -2152,12 +1962,12 @@ const Checkbox = defineComponent(({ props, emit }) => {
2152
1962
  const focused = isFocused();
2153
1963
  const isChecked = checked();
2154
1964
  const disabled = !!props.disabled;
2155
- return /* @__PURE__ */ jsxs$1("box", { children: [
2156
- /* @__PURE__ */ jsx$1("text", {
1965
+ return /* @__PURE__ */ jsxs("box", { children: [
1966
+ /* @__PURE__ */ jsx("text", {
2157
1967
  color: focused ? "cyan" : "white",
2158
1968
  children: focused ? ">" : " "
2159
1969
  }),
2160
- /* @__PURE__ */ jsxs$1("text", {
1970
+ /* @__PURE__ */ jsxs("text", {
2161
1971
  color: disabled ? "white" : isChecked ? "green" : focused ? "cyan" : "white",
2162
1972
  children: [
2163
1973
  "[",
@@ -2165,86 +1975,87 @@ const Checkbox = defineComponent(({ props, emit }) => {
2165
1975
  "]"
2166
1976
  ]
2167
1977
  }),
2168
- label && /* @__PURE__ */ jsxs$1("text", {
1978
+ label && /* @__PURE__ */ jsxs("text", {
2169
1979
  color: disabled ? "white" : focused ? "cyan" : void 0,
2170
1980
  children: [" ", label]
2171
1981
  })
2172
1982
  ] });
2173
1983
  };
2174
1984
  }, { name: "Checkbox" });
2175
-
2176
- //#endregion
2177
- //#region ../runtime-terminal/src/components/Select.tsx
2178
- /** @jsxImportSource @sigx/runtime-core */
2179
- const Select = defineComponent(({ props, emit }) => {
1985
+ const Select = component(({ props, emit }) => {
2180
1986
  const id = Math.random().toString(36).slice(2);
1987
+ let isReady = false;
2181
1988
  const isFocused = () => focusState.activeId === id;
2182
1989
  const getCurrentIndex = () => {
2183
- const idx = (props.options || []).findIndex((o) => o.value === props.value);
1990
+ const idx = (props.options || []).findIndex((o) => o.value === props.model?.value);
2184
1991
  return idx >= 0 ? idx : 0;
2185
1992
  };
2186
1993
  const handleKey = (key) => {
2187
1994
  if (!isFocused()) return;
1995
+ if (!isReady) return;
2188
1996
  const options = props.options || [];
2189
1997
  if (options.length === 0) return;
2190
1998
  const currentIndex = getCurrentIndex();
2191
1999
  if (key === "\x1B[A" || key === "k") {
2192
2000
  const newValue = options[currentIndex > 0 ? currentIndex - 1 : options.length - 1].value;
2193
- emit("update:value", newValue);
2001
+ if (props.model) props.model.value = newValue;
2194
2002
  emit("change", newValue);
2195
2003
  return;
2196
2004
  }
2197
2005
  if (key === "\x1B[B" || key === "j") {
2198
2006
  const newValue = options[currentIndex < options.length - 1 ? currentIndex + 1 : 0].value;
2199
- emit("update:value", newValue);
2007
+ if (props.model) props.model.value = newValue;
2200
2008
  emit("change", newValue);
2201
2009
  return;
2202
2010
  }
2203
2011
  if (key === "\r") {
2204
- emit("submit", props.value || options[0]?.value || "");
2012
+ emit("submit", props.model?.value || options[0]?.value || "");
2205
2013
  return;
2206
2014
  }
2207
2015
  };
2208
2016
  let keyCleanup = null;
2209
- onMount(() => {
2017
+ onMounted(() => {
2210
2018
  registerFocusable(id);
2211
2019
  if (props.autofocus) focus(id);
2212
2020
  keyCleanup = onKey(handleKey);
2021
+ setTimeout(() => {
2022
+ isReady = true;
2023
+ }, 50);
2213
2024
  });
2214
- onCleanup(() => {
2025
+ onUnmounted(() => {
2215
2026
  if (keyCleanup) keyCleanup();
2216
2027
  unregisterFocusable(id);
2217
2028
  });
2218
2029
  return () => {
2219
2030
  const options = props.options || [];
2220
2031
  const focused = isFocused();
2221
- const currentValue = props.value || options[0]?.value || "";
2032
+ const currentValue = props.model?.value || options[0]?.value || "";
2222
2033
  const label = props.label;
2223
- return /* @__PURE__ */ jsx$1("box", {
2034
+ const selectedOption = options.find((o) => o.value === currentValue);
2035
+ const optionElements = options.map((option) => {
2036
+ const isSelected = option.value === currentValue;
2037
+ return /* @__PURE__ */ jsx("box", { children: /* @__PURE__ */ jsxs("text", {
2038
+ color: isSelected ? "cyan" : "white",
2039
+ children: [
2040
+ isSelected ? "❯" : " ",
2041
+ " ",
2042
+ option.label
2043
+ ]
2044
+ }) });
2045
+ });
2046
+ const descriptionElement = props.showDescription && selectedOption?.description ? /* @__PURE__ */ jsx("box", { children: /* @__PURE__ */ jsxs("text", {
2047
+ color: "#666666",
2048
+ children: [" ↳ ", selectedOption.description]
2049
+ }) }) : null;
2050
+ return /* @__PURE__ */ jsxs("box", { children: [/* @__PURE__ */ jsx("box", {
2224
2051
  border: "single",
2225
2052
  borderColor: focused ? "green" : "white",
2226
2053
  label,
2227
- children: options.map((option) => {
2228
- const isSelected = option.value === currentValue;
2229
- return /* @__PURE__ */ jsxs$1("box", { children: [/* @__PURE__ */ jsxs$1("text", {
2230
- color: isSelected ? "cyan" : "white",
2231
- children: [
2232
- isSelected ? "❯" : " ",
2233
- " ",
2234
- option.label
2235
- ]
2236
- }), option.description && isSelected && /* @__PURE__ */ jsxs$1(Fragment$1, { children: [/* @__PURE__ */ jsx$1("br", {}), /* @__PURE__ */ jsxs$1("text", {
2237
- color: "white",
2238
- children: [" ", option.description]
2239
- })] })] });
2240
- })
2241
- });
2054
+ children: optionElements
2055
+ }), descriptionElement] });
2242
2056
  };
2243
2057
  }, { name: "Select" });
2244
-
2245
- //#endregion
2246
- //#region ../runtime-terminal/src/index.ts
2247
- const renderer = createRenderer({
2058
+ const { render } = createRenderer({
2248
2059
  patchProp: (el, key, prev, next) => {
2249
2060
  el.props[key] = next;
2250
2061
  scheduleRender();
@@ -2315,9 +2126,8 @@ const renderer = createRenderer({
2315
2126
  };
2316
2127
  }
2317
2128
  });
2318
- const { render, createApp } = renderer;
2319
- let rootNode = null;
2320
- let isRendering = false;
2129
+ var rootNode = null;
2130
+ var isRendering = false;
2321
2131
  function scheduleRender() {
2322
2132
  if (isRendering) return;
2323
2133
  isRendering = true;
@@ -2333,10 +2143,6 @@ function flushRender() {
2333
2143
  process.stdout.write(lines.join("\x1B[K\n") + "\x1B[K");
2334
2144
  process.stdout.write("\x1B[J");
2335
2145
  }
2336
- /**
2337
- * Check if a node has a box element as an immediate child.
2338
- * This is used to determine if a component wrapper should be treated as a block element.
2339
- */
2340
2146
  function hasBoxChild(node) {
2341
2147
  for (const child of node.children) if (child.tag === "box") return true;
2342
2148
  return false;
@@ -2425,7 +2231,7 @@ function getBorderChars(style) {
2425
2231
  v: "│"
2426
2232
  };
2427
2233
  }
2428
- const keyHandlers = /* @__PURE__ */ new Set();
2234
+ var keyHandlers = /* @__PURE__ */ new Set();
2429
2235
  function onKey(handler) {
2430
2236
  keyHandlers.add(handler);
2431
2237
  return () => keyHandlers.delete(handler);
@@ -2472,16 +2278,7 @@ function renderTerminal(app, options = {}) {
2472
2278
  }
2473
2279
  } };
2474
2280
  }
2475
- let unmountFn = null;
2476
- /**
2477
- * Helper function to mount the terminal for CLI apps.
2478
- * Returns a mount target that can be passed to defineApp().mount().
2479
- *
2480
- * @example
2481
- * ```tsx
2482
- * defineApp(MyApp).mount(mountTerminal());
2483
- * ```
2484
- */
2281
+ var unmountFn = null;
2485
2282
  function mountTerminal(options = { clearConsole: true }) {
2486
2283
  return {
2487
2284
  mount: terminalMount,
@@ -2491,9 +2288,6 @@ function mountTerminal(options = { clearConsole: true }) {
2491
2288
  }
2492
2289
  };
2493
2290
  }
2494
- /**
2495
- * Exit the terminal app cleanly, restoring terminal state.
2496
- */
2497
2291
  function exitTerminal() {
2498
2292
  if (unmountFn) {
2499
2293
  unmountFn();
@@ -2502,20 +2296,6 @@ function exitTerminal() {
2502
2296
  process.stdout.write("\x1B[?25h");
2503
2297
  process.stdout.write("\x1B[2J\x1B[H");
2504
2298
  }
2505
- /**
2506
- * Mount function for Terminal environments.
2507
- * Use this with defineApp().mount() to render to the terminal.
2508
- *
2509
- * @example
2510
- * ```tsx
2511
- * import { defineApp } from '@sigx/runtime-core';
2512
- * import { terminalMount } from '@sigx/runtime-terminal';
2513
- *
2514
- * const app = defineApp(<Counter />);
2515
- * app.use(loggingPlugin)
2516
- * .mount({ clearConsole: true }, terminalMount);
2517
- * ```
2518
- */
2519
2299
  const terminalMount = (component, options, appContext) => {
2520
2300
  rootNode = {
2521
2301
  type: "root",
@@ -2544,7 +2324,6 @@ const terminalMount = (component, options, appContext) => {
2544
2324
  };
2545
2325
  };
2546
2326
  setDefaultMount(terminalMount);
2327
+ export { Button, CLIENT_DIRECTIVES, CLIENT_DIRECTIVE_PREFIX, Checkbox, ComputedSymbol, Fragment, Input, InstanceLifetimes, ProgressBar, Select, SubscriptionHandler, Suspense, Text, Utils, applyContextExtensions, batch, cleanup, component, compound, computed, createEmit, createModel, createModelFromBinding, createPropsAccessor, createPropsProxy, createRenderer, createSlots, createTopic, defineApp, defineFactory, defineInjectable, defineProvide, detectAccess, effect, effectScope, exitTerminal, filterClientDirectives, focus, focusNext, focusPrev, focusState, getAppContextToken, getComponentMeta, getComponentPlugins, getCurrentInstance, getDefaultMount, getHydrationDirective, getModelSymbol, getPlatformModelProcessor, guid, handleComponentError, hasClientDirective, isComponent, isComputed, isLazyComponent, isModel, isReactive, jsx, jsxDEV, jsxs, lazy, mountTerminal, normalizeSubTree, notifyComponentCreated, notifyComponentMounted, notifyComponentUnmounted, notifyComponentUpdated, onCreated, onKey, onMounted, onUnmounted, onUpdated, provideAppContext, registerComponentPlugin, registerContextExtension, registerFocusable, registerPendingPromise, render, renderNodeToLines, renderTerminal, serializeProps, setCurrentInstance, setDefaultMount, setPlatformModelProcessor, signal, terminalMount, toRaw, toSubscriber, track, trigger, unregisterFocusable, untrack, useAppContext, valueOf, watch };
2547
2328
 
2548
- //#endregion
2549
- export { AppContextKey, Button, Checkbox, Fragment, Input, InstanceLifetimes, ProgressBar, Select, SubscriptionHandler, Suspense, Text, Utils, applyContextExtensions, batch, createApp, createPropsAccessor, createPropsProxy, createRenderer, createSlots, createTopic, defineApp, defineComponent, defineFactory, defineInjectable, defineProvide, defineStore, detectAccess, effect, effectScope, exitTerminal, focus, focusNext, focusPrev, focusState, getComponentMeta, getComponentPlugins, getCurrentInstance, getDefaultMount, getPlatformSyncProcessor, guid, handleComponentError, inject, injectApp, isLazyComponent, jsx, jsxDEV, jsxs, lazy, mountTerminal, normalizeSubTree, notifyComponentCreated, notifyComponentMounted, notifyComponentUnmounted, notifyComponentUpdated, onCleanup, onKey, onMount, provide, registerComponentPlugin, registerContextExtension, registerFocusable, registerPendingPromise, render, renderNodeToLines, renderTerminal, setCurrentInstance, setDefaultMount, setPlatformSyncProcessor, signal, terminalMount, toSubscriber, unregisterFocusable, untrack, valueOf, watch };
2550
2329
  //# sourceMappingURL=index.js.map