@sigx/terminal 0.1.25 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,12 @@
1
+ //#region \0rolldown/runtime.js
1
2
  var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
2
- const ComputedSymbol = Symbol("computed");
3
- let activeEffect = null;
3
+ //#endregion
4
+ //#region ../reactivity/src/types.ts
5
+ /** Symbol to identify computed values */
6
+ var ComputedSymbol = Symbol("computed");
7
+ //#endregion
8
+ //#region ../reactivity/src/effect.ts
9
+ var activeEffect = null;
4
10
  var batchDepth = 0;
5
11
  var pendingEffects = /* @__PURE__ */ new Set();
6
12
  function setActiveEffect(effect) {
@@ -9,6 +15,18 @@ function setActiveEffect(effect) {
9
15
  function getActiveEffect() {
10
16
  return activeEffect;
11
17
  }
18
+ /**
19
+ * Batch multiple reactive updates into a single flush.
20
+ * Effects are deferred until the batch completes, avoiding redundant re-renders.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * batch(() => {
25
+ * count.value++;
26
+ * name.value = 'Alice';
27
+ * }); // effects run once after both updates
28
+ * ```
29
+ */
12
30
  function batch(fn) {
13
31
  batchDepth++;
14
32
  try {
@@ -59,9 +77,32 @@ function runEffect(fn) {
59
77
  };
60
78
  return runner;
61
79
  }
80
+ /**
81
+ * Create a reactive effect that re-runs whenever its tracked dependencies change.
82
+ * Returns a runner with a `.stop()` method to dispose the effect.
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * const count = signal(0);
87
+ * const runner = effect(() => console.log(count.value));
88
+ * count.value++; // logs: 1
89
+ * runner.stop();
90
+ * ```
91
+ */
62
92
  function effect(fn) {
63
93
  return runEffect(fn);
64
94
  }
95
+ /**
96
+ * Execute a function without tracking any reactive dependencies.
97
+ * Useful for reading signals inside an effect without creating a subscription.
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * effect(() => {
102
+ * const val = untrack(() => someSignal.value); // not tracked
103
+ * });
104
+ * ```
105
+ */
65
106
  function untrack(fn) {
66
107
  const prev = activeEffect;
67
108
  activeEffect = null;
@@ -71,6 +112,19 @@ function untrack(fn) {
71
112
  activeEffect = prev;
72
113
  }
73
114
  }
115
+ /**
116
+ * Create an effect scope that collects reactive effects for bulk disposal.
117
+ *
118
+ * @example
119
+ * ```ts
120
+ * const scope = effectScope();
121
+ * scope.run(() => {
122
+ * effect(() => console.log(count.value));
123
+ * effect(() => console.log(name.value));
124
+ * });
125
+ * scope.stop(); // disposes both effects
126
+ * ```
127
+ */
74
128
  function effectScope(_detached) {
75
129
  const effects = [];
76
130
  let active = true;
@@ -85,26 +139,49 @@ function effectScope(_detached) {
85
139
  }
86
140
  };
87
141
  }
88
- const ITERATE_KEY = Symbol("iterate");
89
- const reactiveToRaw = /* @__PURE__ */ new WeakMap();
90
- const rawToReactive = /* @__PURE__ */ new WeakMap();
142
+ //#endregion
143
+ //#region ../reactivity/src/collections.ts
144
+ /** Symbol for tracking iteration dependencies (forEach, keys, values, entries, size) */
145
+ var ITERATE_KEY = Symbol("iterate");
146
+ /** WeakMap to get raw object from reactive proxy */
147
+ var reactiveToRaw = /* @__PURE__ */ new WeakMap();
148
+ /** WeakMap to get reactive proxy from raw object */
149
+ var rawToReactive = /* @__PURE__ */ new WeakMap();
150
+ /**
151
+ * Returns the raw, original object from a reactive proxy.
152
+ * If the value is not a proxy, returns it as-is.
153
+ */
91
154
  function toRaw(observed) {
92
155
  const raw = reactiveToRaw.get(observed);
93
156
  return raw ? toRaw(raw) : observed;
94
157
  }
158
+ /**
159
+ * Checks if a value is a reactive proxy created by signal().
160
+ */
95
161
  function isReactive(value) {
96
162
  return reactiveToRaw.has(value);
97
163
  }
164
+ /**
165
+ * Checks if a value is a collection type (Set, Map, WeakSet, WeakMap).
166
+ */
98
167
  function isCollection(value) {
99
168
  if (!value || typeof value !== "object") return false;
100
169
  const ctor = value.constructor;
101
170
  return ctor === Set || ctor === Map || ctor === WeakSet || ctor === WeakMap;
102
171
  }
172
+ /**
173
+ * Checks if a value is an iterable collection (Set or Map, not Weak variants).
174
+ */
103
175
  function isIterableCollection(value) {
104
176
  if (!value || typeof value !== "object") return false;
105
177
  const ctor = value.constructor;
106
178
  return ctor === Set || ctor === Map;
107
179
  }
180
+ /**
181
+ * Checks if a value is an "exotic" built-in object that should NOT be proxied.
182
+ * These objects have internal slots that cannot be accessed through Proxy.
183
+ * Proxying them causes errors like "Method X called on incompatible receiver".
184
+ */
108
185
  function shouldNotProxy(value) {
109
186
  if (!value || typeof value !== "object") return false;
110
187
  const proto = Object.prototype.toString.call(value);
@@ -128,6 +205,11 @@ function shouldNotProxy(value) {
128
205
  "[object BigUint64Array]"
129
206
  ].includes(proto);
130
207
  }
208
+ /**
209
+ * Creates instrumented collection methods that properly handle reactivity.
210
+ * These methods call the real collection methods on the raw object while
211
+ * tracking dependencies and triggering updates.
212
+ */
131
213
  function createCollectionInstrumentations(depsMap, getOrCreateDep) {
132
214
  const instrumentations = {};
133
215
  instrumentations.has = function(key) {
@@ -230,6 +312,9 @@ function createCollectionInstrumentations(depsMap, getOrCreateDep) {
230
312
  };
231
313
  return instrumentations;
232
314
  }
315
+ /**
316
+ * Creates a reactive iterator that wraps values in reactive proxies.
317
+ */
233
318
  function createReactiveIterator(innerIterator, wrapValues) {
234
319
  return {
235
320
  next() {
@@ -248,6 +333,9 @@ function createReactiveIterator(innerIterator, wrapValues) {
248
333
  }
249
334
  };
250
335
  }
336
+ /**
337
+ * Creates a reactive entries iterator that wraps both keys and values.
338
+ */
251
339
  function createReactiveEntriesIterator(innerIterator) {
252
340
  return {
253
341
  next() {
@@ -267,18 +355,37 @@ function createReactiveEntriesIterator(innerIterator) {
267
355
  }
268
356
  };
269
357
  }
358
+ //#endregion
359
+ //#region ../reactivity/src/signal.ts
360
+ /** Check if a value is a primitive type */
270
361
  function isPrimitive(value) {
271
362
  if (value === null || value === void 0) return true;
272
363
  const type = typeof value;
273
364
  return type === "string" || type === "number" || type === "boolean" || type === "symbol" || type === "bigint";
274
365
  }
275
366
  var accessObserver = null;
367
+ /** @internal Get the current access observer for computed/model integration */
276
368
  function getAccessObserver() {
277
369
  return accessObserver;
278
370
  }
371
+ /** @internal Temporarily suspend the access observer (used by computed to prevent leakage) */
279
372
  function setAccessObserver(observer) {
280
373
  accessObserver = observer;
281
374
  }
375
+ /**
376
+ * Detect which reactive property a selector function accesses.
377
+ *
378
+ * Runs `selector()` while observing property accesses and returns the
379
+ * last `[target, key]` pair accessed, or `null` if nothing was read.
380
+ * Used internally by the model/two-way-binding system.
381
+ *
382
+ * @example
383
+ * ```ts
384
+ * const state = signal({ form: { name: 'Alice' } });
385
+ * const result = detectAccess(() => state.form.name);
386
+ * // result === [state.form, 'name']
387
+ * ```
388
+ */
282
389
  function detectAccess(selector) {
283
390
  let result = null;
284
391
  const prev = accessObserver;
@@ -415,6 +522,14 @@ function signal(target) {
415
522
  rawToReactive.set(objectTarget, proxy);
416
523
  return proxy;
417
524
  }
525
+ //#endregion
526
+ //#region ../reactivity/src/watch.ts
527
+ /**
528
+ * Deeply traverses an object to trigger reactive tracking on all nested properties.
529
+ * @param value The value to traverse
530
+ * @param depth Maximum depth to traverse (Infinity for unlimited, number for limited)
531
+ * @param seen Set of already visited objects to prevent circular references
532
+ */
418
533
  function traverse(value, depth = Infinity, seen = /* @__PURE__ */ new Set()) {
419
534
  if (depth <= 0) return value;
420
535
  if (value === null || typeof value !== "object") return value;
@@ -431,6 +546,19 @@ function traverse(value, depth = Infinity, seen = /* @__PURE__ */ new Set()) {
431
546
  else for (const key of Object.keys(value)) traverse(value[key], depth - 1, seen);
432
547
  return value;
433
548
  }
549
+ /**
550
+ * Watch a reactive source and run a callback when it changes.
551
+ * Supports deep watching, immediate invocation, and pause/resume.
552
+ *
553
+ * @example
554
+ * ```ts
555
+ * const count = signal(0);
556
+ * const handle = watch(() => count.value, (newVal, oldVal) => {
557
+ * console.log(`${oldVal} → ${newVal}`);
558
+ * });
559
+ * handle.stop(); // stop watching
560
+ * ```
561
+ */
434
562
  function watch(source, cb, options) {
435
563
  let oldValue;
436
564
  let isFirst = true;
@@ -495,6 +623,8 @@ function watch(source, cb, options) {
495
623
  resume
496
624
  });
497
625
  }
626
+ //#endregion
627
+ //#region ../reactivity/src/computed.ts
498
628
  function computed(getterOrOptions) {
499
629
  let getter;
500
630
  let setter;
@@ -562,20 +692,47 @@ function computed(getterOrOptions) {
562
692
  }
563
693
  return computedObj;
564
694
  }
695
+ /**
696
+ * Type guard to check if a value is a computed signal.
697
+ *
698
+ * @example
699
+ * ```ts
700
+ * const doubled = computed(() => count.value * 2);
701
+ * console.log(isComputed(doubled)); // true
702
+ * console.log(isComputed({ value: 1 })); // false
703
+ * ```
704
+ */
565
705
  function isComputed(value) {
566
706
  return value !== null && typeof value === "object" && ComputedSymbol in value;
567
707
  }
708
+ //#endregion
709
+ //#region ../runtime-core/src/plugins.ts
568
710
  var plugins = [];
711
+ /**
712
+ * Get all registered plugins (internal use)
713
+ */
569
714
  function getComponentPlugins() {
570
715
  return plugins;
571
716
  }
572
717
  var contextExtensions = [];
718
+ /**
719
+ * Apply all registered context extensions to a context object.
720
+ * Called internally by the renderer when creating component contexts.
721
+ */
573
722
  function applyContextExtensions(ctx) {
574
723
  for (const extension of contextExtensions) extension(ctx);
575
724
  }
725
+ //#endregion
726
+ //#region __vite-browser-external
576
727
  var require___vite_browser_external = /* @__PURE__ */ __commonJSMin(((exports, module) => {
577
728
  module.exports = {};
578
729
  }));
730
+ //#endregion
731
+ //#region ../runtime-core/src/async-context.ts
732
+ /**
733
+ * Try to load AsyncLocalStorage from Node.js.
734
+ * Returns null in browser environments.
735
+ */
579
736
  var asyncLocalStorage = null;
580
737
  try {
581
738
  if (typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined") {
@@ -587,6 +744,10 @@ var _fallbackContext = {
587
744
  currentComponentContext: null,
588
745
  currentSuspenseBoundary: null
589
746
  };
747
+ /**
748
+ * Get the current request context.
749
+ * Returns the AsyncLocalStorage store if available, otherwise the module-level fallback.
750
+ */
590
751
  function getRequestContext() {
591
752
  if (asyncLocalStorage) {
592
753
  const store = asyncLocalStorage.getStore();
@@ -594,25 +755,56 @@ function getRequestContext() {
594
755
  }
595
756
  return _fallbackContext;
596
757
  }
758
+ /**
759
+ * Get the current component context (request-safe).
760
+ */
597
761
  function getCurrentInstanceSafe() {
598
762
  return getRequestContext().currentComponentContext;
599
763
  }
764
+ /**
765
+ * Set the current component context (request-safe).
766
+ * Returns the previous value.
767
+ */
600
768
  function setCurrentInstanceSafe(ctx) {
601
769
  const reqCtx = getRequestContext();
602
770
  const prev = reqCtx.currentComponentContext;
603
771
  reqCtx.currentComponentContext = ctx;
604
772
  return prev;
605
773
  }
774
+ /**
775
+ * Get the current suspense boundary (request-safe).
776
+ */
606
777
  function getCurrentSuspenseBoundarySafe() {
607
778
  return getRequestContext().currentSuspenseBoundary;
608
779
  }
780
+ /**
781
+ * Set the current suspense boundary (request-safe).
782
+ * Returns the previous value.
783
+ */
609
784
  function setCurrentSuspenseBoundarySafe(boundary) {
610
785
  const reqCtx = getRequestContext();
611
786
  const prev = reqCtx.currentSuspenseBoundary;
612
787
  reqCtx.currentSuspenseBoundary = boundary;
613
788
  return prev;
614
789
  }
790
+ //#endregion
791
+ //#region ../runtime-core/src/component.ts
615
792
  var currentComponentContext = null;
793
+ /**
794
+ * Returns the setup context of the currently executing component, or `null` if called outside setup.
795
+ *
796
+ * Use this to access the component context (props, emit, etc.) from composable functions
797
+ * or lifecycle hooks that run during component setup.
798
+ *
799
+ * @example
800
+ * ```ts
801
+ * function useMyComposable() {
802
+ * const ctx = getCurrentInstance();
803
+ * if (!ctx) throw new Error('Must be called during component setup');
804
+ * ctx.onMounted(({ el }) => console.log('Mounted to', el));
805
+ * }
806
+ * ```
807
+ */
616
808
  function getCurrentInstance() {
617
809
  return getCurrentInstanceSafe() ?? currentComponentContext;
618
810
  }
@@ -622,26 +814,108 @@ function setCurrentInstance(ctx) {
622
814
  currentComponentContext = ctx;
623
815
  return prevSafe ?? prevModule;
624
816
  }
817
+ /**
818
+ * Register a callback to run after the component is mounted to the DOM.
819
+ * Must be called during component setup.
820
+ *
821
+ * @param fn - Callback receiving a {@link MountContext} with the component's root element.
822
+ *
823
+ * @example
824
+ * ```ts
825
+ * const MyComponent = component(() => {
826
+ * onMounted(({ el }) => {
827
+ * console.log('Mounted to', el);
828
+ * });
829
+ * return () => <div>Hello</div>;
830
+ * });
831
+ * ```
832
+ */
625
833
  function onMounted(fn) {
626
834
  if (currentComponentContext) currentComponentContext.onMounted(fn);
627
835
  else console.warn("onMounted called outside of component setup");
628
836
  }
837
+ /**
838
+ * Register a callback to run when the component is unmounted from the DOM.
839
+ * Must be called during component setup. Use for cleanup (event listeners, timers, subscriptions).
840
+ *
841
+ * @param fn - Callback receiving a {@link MountContext} with the component's root element.
842
+ *
843
+ * @example
844
+ * ```ts
845
+ * const MyComponent = component(() => {
846
+ * const timer = setInterval(() => tick(), 1000);
847
+ * onUnmounted(() => clearInterval(timer));
848
+ * return () => <div>Tick</div>;
849
+ * });
850
+ * ```
851
+ */
629
852
  function onUnmounted(fn) {
630
853
  if (currentComponentContext) currentComponentContext.onUnmounted(fn);
631
854
  else console.warn("onUnmounted called outside of component setup");
632
855
  }
856
+ /**
857
+ * Register a callback to run immediately after component setup completes,
858
+ * before the first render. Must be called during component setup.
859
+ *
860
+ * @example
861
+ * ```ts
862
+ * const MyComponent = component(() => {
863
+ * onCreated(() => console.log('Setup done, about to render'));
864
+ * return () => <div>Hello</div>;
865
+ * });
866
+ * ```
867
+ */
633
868
  function onCreated(fn) {
634
869
  if (currentComponentContext) currentComponentContext.onCreated(fn);
635
870
  else console.warn("onCreated called outside of component setup");
636
871
  }
872
+ /**
873
+ * Register a callback to run after every reactive re-render of the component.
874
+ * Must be called during component setup.
875
+ *
876
+ * @example
877
+ * ```ts
878
+ * const Counter = component(() => {
879
+ * const state = signal({ count: 0 });
880
+ * onUpdated(() => console.log('Re-rendered with count:', state.count));
881
+ * return () => <button onClick={() => state.count++}>{state.count}</button>;
882
+ * });
883
+ * ```
884
+ */
637
885
  function onUpdated(fn) {
638
886
  if (currentComponentContext) currentComponentContext.onUpdated(fn);
639
887
  else console.warn("onUpdated called outside of component setup");
640
888
  }
641
889
  var componentRegistry = /* @__PURE__ */ new Map();
890
+ /**
891
+ * Get component metadata (for DevTools)
892
+ */
642
893
  function getComponentMeta(factory) {
643
894
  return componentRegistry.get(factory);
644
895
  }
896
+ /**
897
+ * Define a component. Returns a JSX factory function.
898
+ *
899
+ * @param setup - Setup function that receives context and returns a render function
900
+ * @param options - Optional configuration (e.g., name for DevTools)
901
+ *
902
+ * @example
903
+ * ```tsx
904
+ * type CardProps = DefineProp<"title", string> & DefineSlot<"header">;
905
+ *
906
+ * export const Card = component<CardProps>((ctx) => {
907
+ * const { title } = ctx.props;
908
+ * const { slots } = ctx;
909
+ *
910
+ * return () => (
911
+ * <div class="card">
912
+ * {slots.header?.() ?? <h2>{title}</h2>}
913
+ * {slots.default()}
914
+ * </div>
915
+ * );
916
+ * });
917
+ * ```
918
+ */
645
919
  function component(setup, options) {
646
920
  const factory = function(props) {
647
921
  return {
@@ -665,6 +939,28 @@ function component(setup, options) {
665
939
  getComponentPlugins().forEach((p) => p.onDefine?.(options?.name, factory, setup));
666
940
  return factory;
667
941
  }
942
+ //#endregion
943
+ //#region ../runtime-core/src/errors.ts
944
+ /**
945
+ * Structured error system for SignalX runtime.
946
+ *
947
+ * Every runtime error has a unique code (SIGX001–SIGX999) so users can
948
+ * programmatically handle errors and look them up in documentation.
949
+ *
950
+ * @example
951
+ * ```ts
952
+ * try {
953
+ * app.mount('#app');
954
+ * } catch (e) {
955
+ * if (e instanceof SigxError && e.code === 'SIGX101') {
956
+ * // handle missing mount target
957
+ * }
958
+ * }
959
+ * ```
960
+ */
961
+ /**
962
+ * Base error class for all SignalX runtime errors.
963
+ */
668
964
  var SigxError = class extends Error {
669
965
  constructor(message, options) {
670
966
  super(message);
@@ -674,7 +970,15 @@ var SigxError = class extends Error {
674
970
  if (options.cause) this.cause = options.cause;
675
971
  }
676
972
  };
677
- const SigxErrorCode = {
973
+ /**
974
+ * Error codes for the SignalX runtime.
975
+ *
976
+ * Ranges:
977
+ * - SIGX001–SIGX099: App lifecycle
978
+ * - SIGX100–SIGX199: Rendering / mounting
979
+ * - SIGX200–SIGX299: Dependency injection
980
+ */
981
+ var SigxErrorCode = {
678
982
  NO_MOUNT_FUNCTION: "SIGX001",
679
983
  RENDER_TARGET_NOT_FOUND: "SIGX100",
680
984
  MOUNT_TARGET_NOT_FOUND: "SIGX101",
@@ -718,8 +1022,23 @@ function provideInvalidInjectableError() {
718
1022
  suggestion: "Create an injectable first:\n const useMyService = defineInjectable(() => new MyService());\n defineProvide(useMyService);"
719
1023
  });
720
1024
  }
1025
+ //#endregion
1026
+ //#region ../runtime-core/src/di/injectable.ts
1027
+ /**
1028
+ * Global singleton instances (fallback when no provider found)
1029
+ */
721
1030
  var globalInstances = /* @__PURE__ */ new Map();
1031
+ /**
1032
+ * Token for the AppContext injectable.
1033
+ * Used to provide/lookup the AppContext in the component tree.
1034
+ */
722
1035
  var appContextToken = Symbol("sigx:appContext");
1036
+ /**
1037
+ * Lookup a provided value by token, traversing component tree.
1038
+ * The AppContext is provided at the root component level, so it's found
1039
+ * just like any other provided value.
1040
+ * @internal
1041
+ */
723
1042
  function lookupProvided(token) {
724
1043
  const ctx = getCurrentInstance();
725
1044
  if (!ctx) return;
@@ -729,6 +1048,10 @@ function lookupProvided(token) {
729
1048
  current = current.parent;
730
1049
  }
731
1050
  }
1051
+ /**
1052
+ * Provide a value at the current component level
1053
+ * @internal
1054
+ */
732
1055
  function provideAtComponent(token, value) {
733
1056
  const ctx = getCurrentInstance();
734
1057
  if (!ctx) throw provideOutsideSetupError();
@@ -736,6 +1059,26 @@ function provideAtComponent(token, value) {
736
1059
  if (!node.provides) node.provides = /* @__PURE__ */ new Map();
737
1060
  node.provides.set(token, value);
738
1061
  }
1062
+ /**
1063
+ * Define an injectable service/value that can be provided at app or component level.
1064
+ *
1065
+ * The returned function can be called to get the current instance:
1066
+ * - If provided at component level via `defineProvide()`, returns that instance
1067
+ * - If provided at app level via `app.defineProvide()`, returns that instance
1068
+ * - Otherwise falls back to a global singleton created by the factory
1069
+ *
1070
+ * @example
1071
+ * ```typescript
1072
+ * // Define a service
1073
+ * const useApiConfig = defineInjectable(() => ({
1074
+ * baseUrl: 'https://api.example.com'
1075
+ * }));
1076
+ *
1077
+ * // Use it in any component - gets nearest provided instance or global singleton
1078
+ * const config = useApiConfig();
1079
+ * console.log(config.baseUrl);
1080
+ * ```
1081
+ */
739
1082
  function defineInjectable(factory) {
740
1083
  const token = Symbol();
741
1084
  const useFn = (() => {
@@ -748,6 +1091,34 @@ function defineInjectable(factory) {
748
1091
  useFn._token = token;
749
1092
  return useFn;
750
1093
  }
1094
+ /**
1095
+ * Provide a new instance of an injectable at the current component level.
1096
+ * Child components will receive this instance when calling the injectable function.
1097
+ *
1098
+ * @param useFn - The injectable function created by defineInjectable
1099
+ * @param factory - Optional custom factory to create the instance (overrides default)
1100
+ *
1101
+ * @example
1102
+ * ```typescript
1103
+ * const useApiConfig = defineInjectable(() => ({ baseUrl: 'https://api.example.com' }));
1104
+ *
1105
+ * const MyComponent = component(() => {
1106
+ * // Create and provide a new instance for this subtree
1107
+ * const config = defineProvide(useApiConfig);
1108
+ * config.baseUrl = 'https://custom.api.com';
1109
+ *
1110
+ * return () => <ChildComponent />;
1111
+ * });
1112
+ *
1113
+ * // Or provide a pre-constructed instance:
1114
+ * const MyComponent2 = component(() => {
1115
+ * const customService = createMyService({ custom: 'options' });
1116
+ * defineProvide(useMyService, () => customService);
1117
+ *
1118
+ * return () => <ChildComponent />;
1119
+ * });
1120
+ * ```
1121
+ */
751
1122
  function defineProvide(useFn, factory) {
752
1123
  const actualFactory = factory ?? useFn._factory;
753
1124
  const token = useFn._token;
@@ -756,31 +1127,110 @@ function defineProvide(useFn, factory) {
756
1127
  provideAtComponent(token, instance);
757
1128
  return instance;
758
1129
  }
1130
+ /**
1131
+ * Get the current AppContext from the component tree.
1132
+ * The AppContext is provided at the root component level during mount/hydrate/SSR.
1133
+ *
1134
+ * @example
1135
+ * ```typescript
1136
+ * const appContext = useAppContext();
1137
+ * console.log(appContext?.app);
1138
+ * ```
1139
+ */
759
1140
  function useAppContext() {
760
1141
  return lookupProvided(appContextToken) ?? null;
761
1142
  }
1143
+ /**
1144
+ * Get the AppContext token.
1145
+ * Used by renderers to provide the AppContext at the root component level.
1146
+ * @internal
1147
+ */
762
1148
  function getAppContextToken() {
763
1149
  return appContextToken;
764
1150
  }
1151
+ /**
1152
+ * Provide the AppContext on a component's provides Map.
1153
+ * Called by the renderer for the ROOT component only.
1154
+ * @internal
1155
+ */
765
1156
  function provideAppContext(ctx, appContext) {
766
1157
  const node = ctx;
767
1158
  if (!node.provides) node.provides = /* @__PURE__ */ new Map();
768
1159
  node.provides.set(appContextToken, appContext);
769
1160
  if (appContext.provides) for (const [token, value] of appContext.provides) node.provides.set(token, value);
770
1161
  }
771
- const __DIRECTIVE__ = Symbol.for("sigx.directive");
1162
+ //#endregion
1163
+ //#region ../runtime-core/src/directives.ts
1164
+ /**
1165
+ * Marker symbol to identify directive definitions.
1166
+ * @internal
1167
+ */
1168
+ var __DIRECTIVE__ = Symbol.for("sigx.directive");
1169
+ /**
1170
+ * Define a directive. This is an identity function that marks the definition
1171
+ * for type inference and runtime identification.
1172
+ *
1173
+ * @example
1174
+ * ```ts
1175
+ * const highlight = defineDirective<string>({
1176
+ * mounted(el, { value }) {
1177
+ * el.style.backgroundColor = value;
1178
+ * },
1179
+ * updated(el, { value }) {
1180
+ * el.style.backgroundColor = value;
1181
+ * }
1182
+ * });
1183
+ * ```
1184
+ */
772
1185
  function defineDirective(definition) {
773
1186
  definition[__DIRECTIVE__] = true;
774
1187
  return definition;
775
1188
  }
1189
+ /**
1190
+ * Check if a value is a directive definition.
1191
+ */
776
1192
  function isDirective(value) {
777
1193
  return value != null && typeof value === "object" && value[__DIRECTIVE__] === true;
778
1194
  }
1195
+ //#endregion
1196
+ //#region ../runtime-core/src/app.ts
779
1197
  var isDev = typeof process !== "undefined" && process.env.NODE_ENV !== "production" || true;
780
1198
  var defaultMountFn = null;
1199
+ /**
1200
+ * Set the default mount function for the platform.
1201
+ * Called by platform packages (runtime-dom, runtime-terminal) on import.
1202
+ *
1203
+ * @example
1204
+ * ```typescript
1205
+ * // In @sigx/runtime-dom
1206
+ * import { setDefaultMount } from '@sigx/runtime-core';
1207
+ * setDefaultMount(domMount);
1208
+ * ```
1209
+ */
781
1210
  function setDefaultMount(mountFn) {
782
1211
  defaultMountFn = mountFn;
783
1212
  }
1213
+ /**
1214
+ * Create an application instance.
1215
+ *
1216
+ * @example
1217
+ * ```tsx
1218
+ * import { defineApp, defineInjectable } from '@sigx/runtime-core';
1219
+ *
1220
+ * // Define an injectable service
1221
+ * const useApiConfig = defineInjectable(() => ({ baseUrl: 'https://api.example.com' }));
1222
+ *
1223
+ * const app = defineApp(<App />);
1224
+ *
1225
+ * app.use(myPlugin, { option: 'value' });
1226
+ *
1227
+ * // Provide custom instance at app level
1228
+ * const config = app.defineProvide(useApiConfig);
1229
+ * config.baseUrl = 'https://custom.api.com';
1230
+ *
1231
+ * app.mount(document.getElementById('app')!);
1232
+ * ```
1233
+ */
784
1234
  function defineApp(rootComponent) {
785
1235
  const installedPlugins = /* @__PURE__ */ new Set();
786
1236
  const context = {
@@ -867,6 +1317,10 @@ function defineApp(rootComponent) {
867
1317
  context.provides.set(appContextToken, context);
868
1318
  return app;
869
1319
  }
1320
+ /**
1321
+ * Notify all app hooks that a component was created.
1322
+ * Called by the renderer after setup() returns.
1323
+ */
870
1324
  function notifyComponentCreated(context, instance) {
871
1325
  if (!context) return;
872
1326
  for (const hooks of context.hooks) try {
@@ -875,6 +1329,10 @@ function notifyComponentCreated(context, instance) {
875
1329
  handleHookError(context, err, instance, "onComponentCreated");
876
1330
  }
877
1331
  }
1332
+ /**
1333
+ * Notify all app hooks that a component was mounted.
1334
+ * Called by the renderer after mount hooks run.
1335
+ */
878
1336
  function notifyComponentMounted(context, instance) {
879
1337
  if (!context) return;
880
1338
  for (const hooks of context.hooks) try {
@@ -883,6 +1341,10 @@ function notifyComponentMounted(context, instance) {
883
1341
  handleHookError(context, err, instance, "onComponentMounted");
884
1342
  }
885
1343
  }
1344
+ /**
1345
+ * Notify all app hooks that a component was unmounted.
1346
+ * Called by the renderer before cleanup.
1347
+ */
886
1348
  function notifyComponentUnmounted(context, instance) {
887
1349
  if (!context) return;
888
1350
  for (const hooks of context.hooks) try {
@@ -891,6 +1353,10 @@ function notifyComponentUnmounted(context, instance) {
891
1353
  handleHookError(context, err, instance, "onComponentUnmounted");
892
1354
  }
893
1355
  }
1356
+ /**
1357
+ * Notify all app hooks that a component updated.
1358
+ * Called by the renderer after re-render.
1359
+ */
894
1360
  function notifyComponentUpdated(context, instance) {
895
1361
  if (!context) return;
896
1362
  for (const hooks of context.hooks) try {
@@ -899,6 +1365,10 @@ function notifyComponentUpdated(context, instance) {
899
1365
  handleHookError(context, err, instance, "onComponentUpdated");
900
1366
  }
901
1367
  }
1368
+ /**
1369
+ * Handle an error in a component. Returns true if the error was handled.
1370
+ * Called by the renderer when an error occurs in setup or render.
1371
+ */
902
1372
  function handleComponentError(context, err, instance, info) {
903
1373
  if (!context) return false;
904
1374
  for (const hooks of context.hooks) try {
@@ -913,16 +1383,84 @@ function handleComponentError(context, err, instance, info) {
913
1383
  }
914
1384
  return false;
915
1385
  }
1386
+ /**
1387
+ * Handle errors that occur in hooks themselves
1388
+ */
916
1389
  function handleHookError(context, err, instance, hookName) {
917
1390
  console.error(`Error in ${hookName} hook:`, err);
918
1391
  if (context.config.errorHandler) try {
919
1392
  context.config.errorHandler(err, instance, `plugin hook: ${hookName}`);
920
1393
  } catch {}
921
1394
  }
1395
+ //#endregion
1396
+ //#region ../runtime-core/src/compound.ts
1397
+ /**
1398
+ * Creates a compound component by attaching sub-components as static properties.
1399
+ *
1400
+ * This enables the pattern of `Parent.Child` components (e.g., `Menu.Item`, `Card.Body`)
1401
+ * while preserving full TypeScript type inference for both the parent and children.
1402
+ *
1403
+ * @param main - The main/parent component factory
1404
+ * @param sub - An object containing sub-components to attach
1405
+ * @returns The main component with sub-components attached as static properties
1406
+ *
1407
+ * @example
1408
+ * ```tsx
1409
+ * // Define individual components
1410
+ * const _Menu = component<MenuProps>(ctx => { ... });
1411
+ * const _MenuItem = component<MenuItemProps>(ctx => { ... });
1412
+ * const _MenuTitle = component<MenuTitleProps>(ctx => { ... });
1413
+ *
1414
+ * // Create compound component
1415
+ * export const Menu = compound(_Menu, {
1416
+ * Item: _MenuItem,
1417
+ * Title: _MenuTitle,
1418
+ * });
1419
+ *
1420
+ * // Usage in JSX
1421
+ * <Menu>
1422
+ * <Menu.Title>Navigation</Menu.Title>
1423
+ * <Menu.Item value="home">Home</Menu.Item>
1424
+ * <Menu.Item value="about">About</Menu.Item>
1425
+ * </Menu>
1426
+ * ```
1427
+ */
922
1428
  function compound(main, sub) {
923
1429
  return Object.assign(main, sub);
924
1430
  }
1431
+ //#endregion
1432
+ //#region ../runtime-core/src/model.ts
1433
+ /**
1434
+ * Model<T> - Unified two-way binding type for SignalX components.
1435
+ *
1436
+ * Provides a single interface for reading, writing, and forwarding model bindings.
1437
+ *
1438
+ * @example
1439
+ * ```tsx
1440
+ * const Input = component<InputProps>(({ props }) => {
1441
+ * // Read
1442
+ * console.log(props.model.value);
1443
+ *
1444
+ * // Write
1445
+ * props.model.value = "new value";
1446
+ *
1447
+ * // Forward to child
1448
+ * <Child model={props.model} />
1449
+ *
1450
+ * // Forward via context
1451
+ * defineProvide(inputContext, () => props.model);
1452
+ * });
1453
+ * ```
1454
+ */
1455
+ /** Symbol to identify Model objects */
925
1456
  var MODEL_SYMBOL = Symbol.for("sigx.model");
1457
+ /**
1458
+ * Creates a Model<T> from a binding tuple and update handler.
1459
+ *
1460
+ * @param tuple - The [sourceObject, key] tuple from reactivity detection
1461
+ * @param updateHandler - Function called when value is set (enables parent interception)
1462
+ * @returns A Model<T> with .value getter/setter and .binding for forwarding
1463
+ */
926
1464
  function createModel(tuple, updateHandler) {
927
1465
  const [obj, key] = tuple;
928
1466
  return {
@@ -942,26 +1480,110 @@ function createModel(tuple, updateHandler) {
942
1480
  [MODEL_SYMBOL]: true
943
1481
  };
944
1482
  }
1483
+ /**
1484
+ * Creates a Model<T> from an existing binding (for forwarding scenarios).
1485
+ *
1486
+ * @param binding - The full binding tuple [obj, key, handler]
1487
+ * @returns A new Model<T> wrapping the same binding
1488
+ */
945
1489
  function createModelFromBinding(binding) {
946
1490
  const [obj, key, handler] = binding;
947
1491
  return createModel([obj, key], handler);
948
1492
  }
1493
+ /**
1494
+ * Type guard to check if a value is a Model<T>.
1495
+ *
1496
+ * Used by JSX runtime to detect forwarded models and extract their bindings.
1497
+ */
949
1498
  function isModel(value) {
950
1499
  return value !== null && typeof value === "object" && MODEL_SYMBOL in value && value[MODEL_SYMBOL] === true;
951
1500
  }
1501
+ //#endregion
1502
+ //#region ../runtime-core/src/platform.ts
952
1503
  var platformModelProcessor = null;
1504
+ /**
1505
+ * Get the current platform model processor (for internal use).
1506
+ */
953
1507
  function getPlatformModelProcessor() {
954
1508
  return platformModelProcessor;
955
1509
  }
1510
+ //#endregion
1511
+ //#region ../runtime-core/src/utils/is-component.ts
1512
+ /**
1513
+ * Check if a value is a SignalX component (has __setup).
1514
+ *
1515
+ * SignalX components are created with component() and have a __setup
1516
+ * property containing the setup function.
1517
+ *
1518
+ * @example
1519
+ * ```ts
1520
+ * const MyComponent = component((ctx) => () => <div/>);
1521
+ * isComponent(MyComponent); // true
1522
+ * isComponent(() => <div/>); // false (plain function component)
1523
+ * isComponent('div'); // false
1524
+ * ```
1525
+ */
956
1526
  function isComponent(type) {
957
1527
  return typeof type === "function" && "__setup" in type;
958
1528
  }
959
- const Fragment = Symbol.for("sigx.Fragment");
960
- const Text = Symbol.for("sigx.Text");
1529
+ //#endregion
1530
+ //#region ../runtime-core/src/jsx-runtime.ts
1531
+ var Fragment = Symbol.for("sigx.Fragment");
1532
+ var Text = Symbol.for("sigx.Text");
1533
+ var Comment = Symbol.for("sigx.Comment");
961
1534
  function normalizeChildren(children) {
962
1535
  if (children == null || children === false || children === true) return [];
963
1536
  if (isComputed(children)) return normalizeChildren(children.value);
964
- if (Array.isArray(children)) return children.flatMap((c) => normalizeChildren(c));
1537
+ if (Array.isArray(children)) return children.map((c) => {
1538
+ if (c == null || c === false || c === true) return {
1539
+ type: Comment,
1540
+ props: {},
1541
+ key: null,
1542
+ children: [],
1543
+ dom: null
1544
+ };
1545
+ if (isComputed(c)) return normalizeChildren(c.value)[0] ?? {
1546
+ type: Comment,
1547
+ props: {},
1548
+ key: null,
1549
+ children: [],
1550
+ dom: null
1551
+ };
1552
+ if (typeof c === "string" || typeof c === "number") return {
1553
+ type: Text,
1554
+ props: {},
1555
+ key: null,
1556
+ children: [],
1557
+ dom: null,
1558
+ text: c
1559
+ };
1560
+ if (Array.isArray(c)) {
1561
+ const nested = normalizeChildren(c);
1562
+ if (nested.length === 0) return {
1563
+ type: Comment,
1564
+ props: {},
1565
+ key: null,
1566
+ children: [],
1567
+ dom: null
1568
+ };
1569
+ if (nested.length === 1) return nested[0];
1570
+ return {
1571
+ type: Fragment,
1572
+ props: {},
1573
+ key: null,
1574
+ children: nested,
1575
+ dom: null
1576
+ };
1577
+ }
1578
+ if (c.type) return c;
1579
+ return {
1580
+ type: Comment,
1581
+ props: {},
1582
+ key: null,
1583
+ children: [],
1584
+ dom: null
1585
+ };
1586
+ });
965
1587
  if (typeof children === "string" || typeof children === "number") return [{
966
1588
  type: Text,
967
1589
  props: {},
@@ -973,6 +1595,9 @@ function normalizeChildren(children) {
973
1595
  if (children.type) return [children];
974
1596
  return [];
975
1597
  }
1598
+ /**
1599
+ * Create a JSX element - this is the core function called by TSX transpilation
1600
+ */
976
1601
  function jsx(type, props, key) {
977
1602
  const processedProps = { ...props };
978
1603
  const models = {};
@@ -1073,11 +1698,26 @@ function jsx(type, props, key) {
1073
1698
  dom: null
1074
1699
  };
1075
1700
  }
1701
+ /**
1702
+ * JSX Factory for fragments
1703
+ */
1076
1704
  function jsxs(type, props, key) {
1077
1705
  return jsx(type, props, key);
1078
1706
  }
1079
- const jsxDEV = jsx;
1707
+ var jsxDEV = jsx;
1708
+ //#endregion
1709
+ //#region ../runtime-core/src/lazy.tsx
1710
+ /**
1711
+ * Lazy loading utilities for sigx components.
1712
+ *
1713
+ * Provides runtime-only lazy loading with no build dependencies.
1714
+ * Works with any bundler that supports dynamic import().
1715
+ */
1080
1716
  var currentSuspenseBoundary = null;
1717
+ /**
1718
+ * Register a promise with the current Suspense boundary
1719
+ * @internal
1720
+ */
1081
1721
  function registerPendingPromise(promise) {
1082
1722
  const boundary = getCurrentSuspenseBoundarySafe() ?? currentSuspenseBoundary;
1083
1723
  if (boundary) {
@@ -1090,6 +1730,33 @@ function registerPendingPromise(promise) {
1090
1730
  }
1091
1731
  return false;
1092
1732
  }
1733
+ /**
1734
+ * Create a lazy-loaded component wrapper.
1735
+ *
1736
+ * The component will be loaded on first render. Use with `<Suspense>` to show
1737
+ * a fallback while loading.
1738
+ *
1739
+ * @param loader - Function that returns a Promise resolving to the component
1740
+ * @returns A component factory that loads the real component on demand
1741
+ *
1742
+ * @example
1743
+ * ```tsx
1744
+ * import { lazy, Suspense } from 'sigx';
1745
+ *
1746
+ * // Component will be in a separate chunk
1747
+ * const HeavyChart = lazy(() => import('./components/HeavyChart'));
1748
+ *
1749
+ * // Usage
1750
+ * <Suspense fallback={<Spinner />}>
1751
+ * <HeavyChart data={chartData} />
1752
+ * </Suspense>
1753
+ *
1754
+ * // Preload on hover
1755
+ * <button onMouseEnter={() => HeavyChart.preload()}>
1756
+ * Show Chart
1757
+ * </button>
1758
+ * ```
1759
+ */
1093
1760
  function lazy(loader) {
1094
1761
  let Component = null;
1095
1762
  let promise = null;
@@ -1173,7 +1840,30 @@ function lazy(loader) {
1173
1840
  };
1174
1841
  return LazyWrapper;
1175
1842
  }
1176
- const Suspense = component((ctx) => {
1843
+ /**
1844
+ * Suspense boundary component for handling async loading states.
1845
+ *
1846
+ * Wraps lazy-loaded components and shows a fallback while they load.
1847
+ *
1848
+ * @example
1849
+ * ```tsx
1850
+ * import { lazy, Suspense } from 'sigx';
1851
+ *
1852
+ * const LazyDashboard = lazy(() => import('./Dashboard'));
1853
+ *
1854
+ * // Basic usage
1855
+ * <Suspense fallback={<div>Loading...</div>}>
1856
+ * <LazyDashboard />
1857
+ * </Suspense>
1858
+ *
1859
+ * // With spinner component
1860
+ * <Suspense fallback={<Spinner size="large" />}>
1861
+ * <LazyDashboard />
1862
+ * <LazyCharts />
1863
+ * </Suspense>
1864
+ * ```
1865
+ */
1866
+ var Suspense = component((ctx) => {
1177
1867
  const { props, slots } = ctx;
1178
1868
  const state = ctx.signal({
1179
1869
  isReady: false,
@@ -1223,9 +1913,48 @@ const Suspense = component((ctx) => {
1223
1913
  }
1224
1914
  };
1225
1915
  }, { name: "Suspense" });
1916
+ /**
1917
+ * Check if a component is a lazy-loaded component
1918
+ */
1226
1919
  function isLazyComponent(component) {
1227
1920
  return component && component.__lazy === true;
1228
1921
  }
1922
+ //#endregion
1923
+ //#region ../runtime-core/src/use-async.ts
1924
+ /**
1925
+ * useAsync — composable for loading async dependencies in components.
1926
+ *
1927
+ * Wraps an async loader in a reactive signal with loading/error states.
1928
+ * No renderer changes required — works with sigx's existing effect system.
1929
+ *
1930
+ * @example
1931
+ * ```tsx
1932
+ * import { component, useAsync } from 'sigx';
1933
+ *
1934
+ * const CodeEditor = component(({ signal: s }) => {
1935
+ * const libs = useAsync(async () => {
1936
+ * const { EditorView } = await import('@codemirror/view');
1937
+ * const { json } = await import('@codemirror/lang-json');
1938
+ * return { EditorView, json };
1939
+ * });
1940
+ *
1941
+ * return () => {
1942
+ * if (libs.loading) return <div class="skeleton" />;
1943
+ * if (libs.error) return <div class="error">{libs.error.message}</div>;
1944
+ * return <div ref={el => new libs.value!.EditorView({ parent: el })} />;
1945
+ * };
1946
+ * });
1947
+ * ```
1948
+ */
1949
+ /**
1950
+ * Load an async resource inside a component's setup function.
1951
+ *
1952
+ * Returns a reactive object with `value`, `loading`, and `error` fields.
1953
+ * The component's render function re-runs automatically when the state changes.
1954
+ *
1955
+ * @param loader — async function that returns the resource
1956
+ * @returns reactive AsyncState
1957
+ */
1229
1958
  function useAsync(loader) {
1230
1959
  const state = signal({
1231
1960
  value: null,
@@ -1245,7 +1974,38 @@ function useAsync(loader) {
1245
1974
  });
1246
1975
  return state;
1247
1976
  }
1248
- const ErrorBoundary = component((ctx) => {
1977
+ //#endregion
1978
+ //#region ../runtime-core/src/error-boundary.ts
1979
+ /**
1980
+ * ErrorBoundary component for catching render errors.
1981
+ *
1982
+ * Catches errors thrown during child component rendering and displays
1983
+ * a fallback UI. Works during both SSR and client-side rendering.
1984
+ *
1985
+ * @example
1986
+ * ```tsx
1987
+ * import { ErrorBoundary } from 'sigx';
1988
+ *
1989
+ * <ErrorBoundary
1990
+ * fallback={(error, retry) => (
1991
+ * <div>
1992
+ * <p>Something went wrong: {error.message}</p>
1993
+ * <button onClick={retry}>Retry</button>
1994
+ * </div>
1995
+ * )}
1996
+ * >
1997
+ * <RiskyComponent />
1998
+ * </ErrorBoundary>
1999
+ * ```
2000
+ */
2001
+ /**
2002
+ * ErrorBoundary component.
2003
+ *
2004
+ * Wraps children and catches errors thrown during rendering.
2005
+ * When an error occurs, displays the `fallback` UI.
2006
+ * Provides a `retry` function to reset and re-render children.
2007
+ */
2008
+ var ErrorBoundary = component((ctx) => {
1249
2009
  const { fallback } = ctx.props;
1250
2010
  const { slots } = ctx;
1251
2011
  const state = ctx.signal({
@@ -1273,6 +2033,8 @@ const ErrorBoundary = component((ctx) => {
1273
2033
  }
1274
2034
  };
1275
2035
  }, { name: "ErrorBoundary" });
2036
+ //#endregion
2037
+ //#region ../runtime-core/src/utils/index.ts
1276
2038
  var Utils = class {
1277
2039
  static isPromise(value) {
1278
2040
  return !!value && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
@@ -1284,13 +2046,17 @@ function guid$1() {
1284
2046
  return (c == "x" ? r : r & 3 | 8).toString(16);
1285
2047
  });
1286
2048
  }
1287
- const guid = guid$1;
1288
- let InstanceLifetimes = /* @__PURE__ */ function(InstanceLifetimes) {
2049
+ //#endregion
2050
+ //#region ../runtime-core/src/models/index.ts
2051
+ var guid = guid$1;
2052
+ var InstanceLifetimes = /* @__PURE__ */ function(InstanceLifetimes) {
1289
2053
  InstanceLifetimes[InstanceLifetimes["Transient"] = 0] = "Transient";
1290
2054
  InstanceLifetimes[InstanceLifetimes["Scoped"] = 1] = "Scoped";
1291
2055
  InstanceLifetimes[InstanceLifetimes["Singleton"] = 2] = "Singleton";
1292
2056
  return InstanceLifetimes;
1293
2057
  }({});
2058
+ //#endregion
2059
+ //#region ../runtime-core/src/messaging/index.ts
1294
2060
  function createTopic(_options) {
1295
2061
  let subscribers = [];
1296
2062
  const publish = (data) => {
@@ -1319,6 +2085,8 @@ function createTopic(_options) {
1319
2085
  function toSubscriber(topic) {
1320
2086
  return { subscribe: (handler) => topic.subscribe(handler) };
1321
2087
  }
2088
+ //#endregion
2089
+ //#region ../runtime-core/src/di/factory.ts
1322
2090
  var SubscriptionHandler = class {
1323
2091
  constructor() {
1324
2092
  this.unsubs = [];
@@ -1358,6 +2126,21 @@ function defineFactory(setup, _lifetime, _typeIdentifier) {
1358
2126
  if (setup.length <= 1) return defineInjectable(() => factoryCreator());
1359
2127
  return factoryCreator;
1360
2128
  }
2129
+ //#endregion
2130
+ //#region ../runtime-core/src/utils/props-accessor.ts
2131
+ /**
2132
+ * Creates a props accessor - a simple reactive proxy for props.
2133
+ * Use destructuring with defaults for optional props.
2134
+ *
2135
+ * @example
2136
+ * ```ts
2137
+ * // In component setup:
2138
+ * const { count = 0, label = 'Default' } = ctx.props;
2139
+ *
2140
+ * // Or spread to forward props
2141
+ * <ChildComponent {...ctx.props} />
2142
+ * ```
2143
+ */
1361
2144
  function createPropsAccessor(reactiveProps) {
1362
2145
  return new Proxy(reactiveProps, {
1363
2146
  get(target, key) {
@@ -1381,6 +2164,39 @@ function createPropsAccessor(reactiveProps) {
1381
2164
  }
1382
2165
  });
1383
2166
  }
2167
+ //#endregion
2168
+ //#region ../runtime-core/src/utils/slots.ts
2169
+ /**
2170
+ * Slots system for component children.
2171
+ * Supports default and named slots with reactivity.
2172
+ */
2173
+ /**
2174
+ * Create slots object from children and slots prop.
2175
+ * Uses a version signal to trigger re-renders when children change.
2176
+ *
2177
+ * Supports named slots via:
2178
+ * - `slots` prop object (e.g., `slots={{ header: () => <div>...</div> }}`)
2179
+ * - `slot` prop on children (e.g., `<div slot="header">...</div>`)
2180
+ *
2181
+ * @example
2182
+ * ```tsx
2183
+ * // Parent component
2184
+ * <Card slots={{ header: () => <h1>Title</h1> }}>
2185
+ * <p>Default content</p>
2186
+ * <span slot="footer">Footer text</span>
2187
+ * </Card>
2188
+ *
2189
+ * // Card component setup
2190
+ * const slots = createSlots(children, slotsFromProps);
2191
+ * return () => (
2192
+ * <div>
2193
+ * {slots.header()}
2194
+ * {slots.default()}
2195
+ * {slots.footer()}
2196
+ * </div>
2197
+ * );
2198
+ * ```
2199
+ */
1384
2200
  function createSlots(children, slotsFromProps) {
1385
2201
  const versionSignal = signal({ v: 0 });
1386
2202
  function extractNamedSlotsFromChildren(c) {
@@ -1401,7 +2217,7 @@ function createSlots(children, slotsFromProps) {
1401
2217
  namedSlots
1402
2218
  };
1403
2219
  }
1404
- const slotsObj = {
2220
+ return new Proxy({
1405
2221
  _children: children,
1406
2222
  _slotsFromProps: slotsFromProps || {},
1407
2223
  _version: versionSignal,
@@ -1412,8 +2228,7 @@ function createSlots(children, slotsFromProps) {
1412
2228
  const { defaultChildren } = extractNamedSlotsFromChildren(c);
1413
2229
  return defaultChildren.filter((child) => child != null && child !== false && child !== true);
1414
2230
  }
1415
- };
1416
- return new Proxy(slotsObj, { get(target, prop) {
2231
+ }, { get(target, prop) {
1417
2232
  if (prop in target) return target[prop];
1418
2233
  if (typeof prop === "string") return function(scopedProps) {
1419
2234
  target._version.v;
@@ -1427,6 +2242,39 @@ function createSlots(children, slotsFromProps) {
1427
2242
  };
1428
2243
  } });
1429
2244
  }
2245
+ //#endregion
2246
+ //#region ../runtime-core/src/utils/normalize.ts
2247
+ /**
2248
+ * VNode normalization utilities.
2249
+ * Converts render results into proper VNode structures.
2250
+ */
2251
+ /**
2252
+ * Normalize render result to a VNode (wrapping arrays in Fragment).
2253
+ * Handles null, undefined, false, true by returning an empty Text node.
2254
+ *
2255
+ * This is used to normalize the return value of component render functions
2256
+ * into a consistent VNode structure for the renderer to process.
2257
+ *
2258
+ * @example
2259
+ * ```ts
2260
+ * // Conditional rendering returns null/false
2261
+ * normalizeSubTree(null) // → empty Text node
2262
+ * normalizeSubTree(false) // → empty Text node
2263
+ *
2264
+ * // Arrays become Fragments
2265
+ * normalizeSubTree([<A/>, <B/>]) // → Fragment with children
2266
+ *
2267
+ * // Primitives become Text nodes
2268
+ * normalizeSubTree("hello") // → Text node
2269
+ * normalizeSubTree(42) // → Text node
2270
+ *
2271
+ * // Computed signals are auto-unwrapped
2272
+ * normalizeSubTree(computed(() => "hi")) // → Text node with "hi"
2273
+ *
2274
+ * // VNodes pass through
2275
+ * normalizeSubTree(<div/>) // → same VNode
2276
+ * ```
2277
+ */
1430
2278
  function normalizeSubTree(result) {
1431
2279
  if (result == null || result === false || result === true) return {
1432
2280
  type: Text,
@@ -1454,14 +2302,41 @@ function normalizeSubTree(result) {
1454
2302
  };
1455
2303
  return result;
1456
2304
  }
1457
- const CLIENT_DIRECTIVE_PREFIX = "client:";
1458
- const CLIENT_DIRECTIVES = [
2305
+ //#endregion
2306
+ //#region ../runtime-core/src/hydration/index.ts
2307
+ /**
2308
+ * Hydration utilities for SSR
2309
+ *
2310
+ * These utilities are shared between server-side rendering (stream.ts)
2311
+ * and client-side hydration (hydrate.ts). They are placed in runtime-core
2312
+ * to allow any SSR implementation to use them.
2313
+ *
2314
+ * @module
2315
+ */
2316
+ /**
2317
+ * Client directive prefix used for selective hydration
2318
+ */
2319
+ var CLIENT_DIRECTIVE_PREFIX = "client:";
2320
+ /**
2321
+ * Valid client directive names
2322
+ */
2323
+ var CLIENT_DIRECTIVES = [
1459
2324
  "client:load",
1460
2325
  "client:idle",
1461
2326
  "client:visible",
1462
2327
  "client:media",
1463
2328
  "client:only"
1464
2329
  ];
2330
+ /**
2331
+ * Create an emit function for component context.
2332
+ * This is a common pattern used in both mountComponent and hydrateComponent.
2333
+ *
2334
+ * @example
2335
+ * ```ts
2336
+ * const emit = createEmit(reactiveProps);
2337
+ * emit('click', eventData); // Calls props.onClick(eventData)
2338
+ * ```
2339
+ */
1465
2340
  function createEmit(reactiveProps) {
1466
2341
  return (event, ...args) => {
1467
2342
  const eventName = `on${event[0].toUpperCase() + event.slice(1)}`;
@@ -1469,6 +2344,8 @@ function createEmit(reactiveProps) {
1469
2344
  if (handler && typeof handler === "function") handler(...args);
1470
2345
  };
1471
2346
  }
2347
+ //#endregion
2348
+ //#region ../runtime-core/src/renderer.ts
1472
2349
  function createRenderer(options) {
1473
2350
  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, patchDirective: hostPatchDirective, onElementMounted: hostOnElementMounted, onElementUnmounted: hostOnElementUnmounted, getActiveElement: hostGetActiveElement, restoreFocus: hostRestoreFocus } = options;
1474
2351
  let currentAppContext = null;
@@ -1575,6 +2452,12 @@ function createRenderer(options) {
1575
2452
  hostInsert(node, container, before);
1576
2453
  return;
1577
2454
  }
2455
+ if (vnode.type === Comment) {
2456
+ const node = hostCreateComment("");
2457
+ vnode.dom = node;
2458
+ hostInsert(node, container, before);
2459
+ return;
2460
+ }
1578
2461
  if (vnode.type === Fragment) {
1579
2462
  const anchor = hostCreateComment("");
1580
2463
  vnode.dom = anchor;
@@ -1627,6 +2510,10 @@ function createRenderer(options) {
1627
2510
  if (vnode.dom) hostRemove(vnode.dom);
1628
2511
  return;
1629
2512
  }
2513
+ if (vnode.type === Comment) {
2514
+ if (vnode.dom) hostRemove(vnode.dom);
2515
+ return;
2516
+ }
1630
2517
  if (vnode.props?.ref) untrack(() => {
1631
2518
  if (typeof vnode.props.ref === "function") vnode.props.ref(null);
1632
2519
  else if (vnode.props.ref && typeof vnode.props.ref === "object") vnode.props.ref.current = null;
@@ -1706,6 +2593,10 @@ function createRenderer(options) {
1706
2593
  if (oldVNode.text !== newVNode.text) hostSetText(newVNode.dom, String(newVNode.text));
1707
2594
  return;
1708
2595
  }
2596
+ if (newVNode.type === Comment) {
2597
+ newVNode.dom = oldVNode.dom;
2598
+ return;
2599
+ }
1709
2600
  if (newVNode.type === Fragment) {
1710
2601
  patchChildren(oldVNode, newVNode, container, false);
1711
2602
  return;
@@ -1737,6 +2628,9 @@ function createRenderer(options) {
1737
2628
  newChildren.forEach((c) => c.parent = newVNode);
1738
2629
  reconcileChildrenArray(container, oldChildren, newChildren, parentIsSVG);
1739
2630
  }
2631
+ /**
2632
+ * Check for duplicate keys in an array of VNodes and warn in development.
2633
+ */
1740
2634
  function checkDuplicateKeys(children) {
1741
2635
  if (process.env.NODE_ENV === "production") return;
1742
2636
  const seenKeys = /* @__PURE__ */ new Set();
@@ -1956,8 +2850,10 @@ function createRenderer(options) {
1956
2850
  mountComponent
1957
2851
  };
1958
2852
  }
2853
+ //#endregion
2854
+ //#region ../runtime-terminal/src/focus.ts
1959
2855
  var focusableIds = /* @__PURE__ */ new Set();
1960
- const focusState = signal({ activeId: null });
2856
+ var focusState = signal({ activeId: null });
1961
2857
  function registerFocusable(id) {
1962
2858
  focusableIds.add(id);
1963
2859
  if (focusState.activeId === null) focusState.activeId = id;
@@ -1982,6 +2878,8 @@ function focusPrev() {
1982
2878
  const ids = Array.from(focusableIds);
1983
2879
  focusState.activeId = ids[((focusState.activeId ? ids.indexOf(focusState.activeId) : -1) - 1 + ids.length) % ids.length];
1984
2880
  }
2881
+ //#endregion
2882
+ //#region ../runtime-terminal/src/utils.ts
1985
2883
  function getColorCode(color) {
1986
2884
  switch (color) {
1987
2885
  case "red": return "\x1B[31m";
@@ -2009,7 +2907,10 @@ function getBackgroundColorCode(color) {
2009
2907
  function stripAnsi(str) {
2010
2908
  return str.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "");
2011
2909
  }
2012
- const Input = component(({ props, emit }) => {
2910
+ //#endregion
2911
+ //#region ../runtime-terminal/src/components/Input.tsx
2912
+ /** @jsxImportSource @sigx/runtime-core */
2913
+ var Input = component(({ props, emit }) => {
2013
2914
  const id = Math.random().toString(36).slice(2);
2014
2915
  let isReady = false;
2015
2916
  const isFocused = () => focusState.activeId === id;
@@ -2064,7 +2965,10 @@ const Input = component(({ props, emit }) => {
2064
2965
  });
2065
2966
  };
2066
2967
  }, { name: "Input" });
2067
- const ProgressBar = component(({ props }) => {
2968
+ //#endregion
2969
+ //#region ../runtime-terminal/src/components/ProgressBar.tsx
2970
+ /** @jsxImportSource @sigx/runtime-core */
2971
+ var ProgressBar = component(({ props }) => {
2068
2972
  return () => {
2069
2973
  const value = props.value || 0;
2070
2974
  const max = props.max || 100;
@@ -2080,7 +2984,10 @@ const ProgressBar = component(({ props }) => {
2080
2984
  return /* @__PURE__ */ jsx("box", { children: /* @__PURE__ */ jsx("text", { children: colorCode + barChar.repeat(filledLen) + emptyChar.repeat(emptyLen) + reset + ` ${Math.round(percentage * 100)}%` }) });
2081
2985
  };
2082
2986
  }, { name: "ProgressBar" });
2083
- const Button = component(({ props, emit }) => {
2987
+ //#endregion
2988
+ //#region ../runtime-terminal/src/components/Button.tsx
2989
+ /** @jsxImportSource @sigx/runtime-core */
2990
+ var Button = component(({ props, emit }) => {
2084
2991
  const id = Math.random().toString(36).slice(2);
2085
2992
  const isFocused = () => focusState.activeId === id;
2086
2993
  const pressed = signal({ value: false });
@@ -2123,7 +3030,10 @@ const Button = component(({ props, emit }) => {
2123
3030
  });
2124
3031
  };
2125
3032
  }, { name: "Button" });
2126
- const Checkbox = component(({ props, emit }) => {
3033
+ //#endregion
3034
+ //#region ../runtime-terminal/src/components/Checkbox.tsx
3035
+ /** @jsxImportSource @sigx/runtime-core */
3036
+ var Checkbox = component(({ props, emit }) => {
2127
3037
  const id = Math.random().toString(36).slice(2);
2128
3038
  const isFocused = () => focusState.activeId === id;
2129
3039
  const checked = () => !!props.model?.value;
@@ -2171,7 +3081,10 @@ const Checkbox = component(({ props, emit }) => {
2171
3081
  ] });
2172
3082
  };
2173
3083
  }, { name: "Checkbox" });
2174
- const Select = component(({ props, emit }) => {
3084
+ //#endregion
3085
+ //#region ../runtime-terminal/src/components/Select.tsx
3086
+ /** @jsxImportSource @sigx/runtime-core */
3087
+ var Select = component(({ props, emit }) => {
2175
3088
  const id = Math.random().toString(36).slice(2);
2176
3089
  let isReady = false;
2177
3090
  const isFocused = () => focusState.activeId === id;
@@ -2244,7 +3157,7 @@ const Select = component(({ props, emit }) => {
2244
3157
  }), descriptionElement] });
2245
3158
  };
2246
3159
  }, { name: "Select" });
2247
- const { render } = createRenderer({
3160
+ var { render } = createRenderer({
2248
3161
  patchProp: (el, key, prev, next) => {
2249
3162
  el.props[key] = next;
2250
3163
  scheduleRender();
@@ -2332,6 +3245,10 @@ function flushRender() {
2332
3245
  process.stdout.write(lines.join("\x1B[K\n") + "\x1B[K");
2333
3246
  process.stdout.write("\x1B[J");
2334
3247
  }
3248
+ /**
3249
+ * Check if a node has a box element as an immediate child.
3250
+ * This is used to determine if a component wrapper should be treated as a block element.
3251
+ */
2335
3252
  function hasBoxChild(node) {
2336
3253
  for (const child of node.children) if (child.tag === "box") return true;
2337
3254
  return false;
@@ -2468,6 +3385,15 @@ function renderTerminal(app, options = {}) {
2468
3385
  } };
2469
3386
  }
2470
3387
  var unmountFn = null;
3388
+ /**
3389
+ * Helper function to mount the terminal for CLI apps.
3390
+ * Returns a mount target that can be passed to defineApp().mount().
3391
+ *
3392
+ * @example
3393
+ * ```tsx
3394
+ * defineApp(MyApp).mount(mountTerminal());
3395
+ * ```
3396
+ */
2471
3397
  function mountTerminal(options = { clearConsole: true }) {
2472
3398
  return {
2473
3399
  mount: terminalMount,
@@ -2477,6 +3403,9 @@ function mountTerminal(options = { clearConsole: true }) {
2477
3403
  }
2478
3404
  };
2479
3405
  }
3406
+ /**
3407
+ * Exit the terminal app cleanly, restoring terminal state.
3408
+ */
2480
3409
  function exitTerminal() {
2481
3410
  if (unmountFn) {
2482
3411
  unmountFn();
@@ -2485,7 +3414,21 @@ function exitTerminal() {
2485
3414
  process.stdout.write("\x1B[?25h");
2486
3415
  process.stdout.write("\x1B[2J\x1B[H");
2487
3416
  }
2488
- const terminalMount = (component, options, appContext) => {
3417
+ /**
3418
+ * Mount function for Terminal environments.
3419
+ * Use this with defineApp().mount() to render to the terminal.
3420
+ *
3421
+ * @example
3422
+ * ```tsx
3423
+ * import { defineApp } from '@sigx/runtime-core';
3424
+ * import { terminalMount } from '@sigx/runtime-terminal';
3425
+ *
3426
+ * const app = defineApp(<Counter />);
3427
+ * app.use(loggingPlugin)
3428
+ * .mount({ clearConsole: true }, terminalMount);
3429
+ * ```
3430
+ */
3431
+ var terminalMount = (component, options, appContext) => {
2489
3432
  rootNode = {
2490
3433
  type: "root",
2491
3434
  props: {},
@@ -2513,6 +3456,7 @@ const terminalMount = (component, options, appContext) => {
2513
3456
  };
2514
3457
  };
2515
3458
  setDefaultMount(terminalMount);
2516
- export { Button, CLIENT_DIRECTIVES, CLIENT_DIRECTIVE_PREFIX, Checkbox, ComputedSymbol, ErrorBoundary, Fragment, Input, InstanceLifetimes, ProgressBar, Select, SigxError, SigxErrorCode, SubscriptionHandler, Suspense, Text, Utils, asyncSetupClientError, batch, component, compound, computed, createModel, createModelFromBinding, createTopic, defineApp, defineDirective, defineFactory, defineInjectable, defineProvide, detectAccess, effect, effectScope, exitTerminal, focus, focusNext, focusPrev, focusState, getComponentMeta, getCurrentInstance, guid, isComponent, isComputed, isDirective, isLazyComponent, isModel, isReactive, jsx, jsxDEV, jsxs, lazy, mountTargetNotFoundError, mountTerminal, noMountFunctionError, onCreated, onKey, onMounted, onUnmounted, onUpdated, provideInvalidInjectableError, provideOutsideSetupError, registerFocusable, render, renderNodeToLines, renderTargetNotFoundError, renderTerminal, signal, terminalMount, toRaw, toSubscriber, unregisterFocusable, untrack, useAppContext, useAsync, watch };
3459
+ //#endregion
3460
+ export { Button, CLIENT_DIRECTIVES, CLIENT_DIRECTIVE_PREFIX, Checkbox, Comment, ComputedSymbol, ErrorBoundary, Fragment, Input, InstanceLifetimes, ProgressBar, Select, SigxError, SigxErrorCode, SubscriptionHandler, Suspense, Text, Utils, asyncSetupClientError, batch, component, compound, computed, createModel, createModelFromBinding, createTopic, defineApp, defineDirective, defineFactory, defineInjectable, defineProvide, detectAccess, effect, effectScope, exitTerminal, focus, focusNext, focusPrev, focusState, getComponentMeta, getCurrentInstance, guid, isComponent, isComputed, isDirective, isLazyComponent, isModel, isReactive, jsx, jsxDEV, jsxs, lazy, mountTargetNotFoundError, mountTerminal, noMountFunctionError, onCreated, onKey, onMounted, onUnmounted, onUpdated, provideInvalidInjectableError, provideOutsideSetupError, registerFocusable, render, renderNodeToLines, renderTargetNotFoundError, renderTerminal, signal, terminalMount, toRaw, toSubscriber, unregisterFocusable, untrack, useAppContext, useAsync, watch };
2517
3461
 
2518
3462
  //# sourceMappingURL=index.js.map