@sigx/terminal 0.1.3 → 0.1.4
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 +474 -58
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -16,15 +16,17 @@ function batch(fn) {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
function runEffect(fn) {
|
|
19
|
-
const
|
|
20
|
-
cleanup(
|
|
21
|
-
activeEffect =
|
|
19
|
+
const effectFn = function() {
|
|
20
|
+
cleanup(effectFn);
|
|
21
|
+
activeEffect = effectFn;
|
|
22
22
|
fn();
|
|
23
23
|
activeEffect = null;
|
|
24
24
|
};
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
effectFn.deps = [];
|
|
26
|
+
effectFn();
|
|
27
|
+
const runner = (() => effectFn());
|
|
28
|
+
runner.stop = () => cleanup(effectFn);
|
|
29
|
+
return runner;
|
|
28
30
|
}
|
|
29
31
|
function cleanup(effect$1) {
|
|
30
32
|
if (!effect$1.deps) return;
|
|
@@ -158,8 +160,16 @@ function watch(source, cb, options) {
|
|
|
158
160
|
let oldValue;
|
|
159
161
|
let isFirst = true;
|
|
160
162
|
let cleanupFn = null;
|
|
163
|
+
let paused = false;
|
|
164
|
+
let pendingValue;
|
|
165
|
+
let hasPending = false;
|
|
161
166
|
const runner = effect(() => {
|
|
162
167
|
const newValue = typeof source === "function" ? source() : source;
|
|
168
|
+
if (paused) {
|
|
169
|
+
pendingValue = newValue;
|
|
170
|
+
hasPending = true;
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
163
173
|
if (isFirst) {
|
|
164
174
|
if (options?.immediate) {
|
|
165
175
|
if (cleanupFn) cleanupFn();
|
|
@@ -173,14 +183,28 @@ function watch(source, cb, options) {
|
|
|
173
183
|
oldValue = newValue;
|
|
174
184
|
});
|
|
175
185
|
const stop = () => {
|
|
176
|
-
runner();
|
|
186
|
+
runner.stop();
|
|
177
187
|
if (cleanupFn) cleanupFn();
|
|
178
188
|
};
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
189
|
+
const pause = () => {
|
|
190
|
+
paused = true;
|
|
191
|
+
};
|
|
192
|
+
const resume = () => {
|
|
193
|
+
if (!paused) return;
|
|
194
|
+
paused = false;
|
|
195
|
+
if (hasPending && !Object.is(pendingValue, oldValue)) {
|
|
196
|
+
if (cleanupFn) cleanupFn();
|
|
197
|
+
cb(pendingValue, oldValue, (fn) => cleanupFn = fn);
|
|
198
|
+
oldValue = pendingValue;
|
|
199
|
+
}
|
|
200
|
+
hasPending = false;
|
|
201
|
+
pendingValue = void 0;
|
|
202
|
+
};
|
|
203
|
+
return Object.assign(stop, {
|
|
204
|
+
stop,
|
|
205
|
+
pause,
|
|
206
|
+
resume
|
|
207
|
+
});
|
|
184
208
|
}
|
|
185
209
|
function effectScope(detached) {
|
|
186
210
|
const effects = [];
|
|
@@ -216,15 +240,15 @@ function getPlatformSyncProcessor() {
|
|
|
216
240
|
|
|
217
241
|
//#endregion
|
|
218
242
|
//#region ../runtime-core/src/plugins.ts
|
|
219
|
-
const plugins = [];
|
|
243
|
+
const plugins$1 = [];
|
|
220
244
|
function registerComponentPlugin(plugin) {
|
|
221
|
-
plugins.push(plugin);
|
|
245
|
+
plugins$1.push(plugin);
|
|
222
246
|
}
|
|
223
247
|
/**
|
|
224
248
|
* Get all registered plugins (internal use)
|
|
225
249
|
*/
|
|
226
250
|
function getComponentPlugins() {
|
|
227
|
-
return plugins;
|
|
251
|
+
return plugins$1;
|
|
228
252
|
}
|
|
229
253
|
|
|
230
254
|
//#endregion
|
|
@@ -442,12 +466,12 @@ function onCleanup(fn) {
|
|
|
442
466
|
if (currentComponentContext) currentComponentContext.onCleanup(fn);
|
|
443
467
|
else console.warn("onCleanup called outside of component setup");
|
|
444
468
|
}
|
|
445
|
-
const componentRegistry = /* @__PURE__ */ new Map();
|
|
469
|
+
const componentRegistry$1 = /* @__PURE__ */ new Map();
|
|
446
470
|
/**
|
|
447
471
|
* Get component metadata (for DevTools)
|
|
448
472
|
*/
|
|
449
473
|
function getComponentMeta(factory) {
|
|
450
|
-
return componentRegistry.get(factory);
|
|
474
|
+
return componentRegistry$1.get(factory);
|
|
451
475
|
}
|
|
452
476
|
/**
|
|
453
477
|
* Helper to create a proxy that tracks property access
|
|
@@ -497,7 +521,7 @@ function defineComponent(setup, options) {
|
|
|
497
521
|
factory.__events = null;
|
|
498
522
|
factory.__ref = null;
|
|
499
523
|
factory.__slots = null;
|
|
500
|
-
componentRegistry.set(factory, {
|
|
524
|
+
componentRegistry$1.set(factory, {
|
|
501
525
|
name: options?.name,
|
|
502
526
|
setup
|
|
503
527
|
});
|
|
@@ -603,6 +627,190 @@ function jsxs(type, props, key) {
|
|
|
603
627
|
}
|
|
604
628
|
const jsxDEV = jsx;
|
|
605
629
|
|
|
630
|
+
//#endregion
|
|
631
|
+
//#region ../runtime-core/src/lazy.tsx
|
|
632
|
+
/**
|
|
633
|
+
* Lazy loading utilities for sigx components.
|
|
634
|
+
*
|
|
635
|
+
* Provides runtime-only lazy loading with no build dependencies.
|
|
636
|
+
* Works with any bundler that supports dynamic import().
|
|
637
|
+
*/
|
|
638
|
+
let currentSuspenseBoundary$1 = null;
|
|
639
|
+
/**
|
|
640
|
+
* Register a promise with the current Suspense boundary
|
|
641
|
+
* @internal
|
|
642
|
+
*/
|
|
643
|
+
function registerPendingPromise(promise) {
|
|
644
|
+
const boundary = currentSuspenseBoundary$1;
|
|
645
|
+
if (boundary) {
|
|
646
|
+
boundary.pending.add(promise);
|
|
647
|
+
promise.finally(() => {
|
|
648
|
+
boundary.pending.delete(promise);
|
|
649
|
+
if (boundary.pending.size === 0) boundary.onResolve();
|
|
650
|
+
});
|
|
651
|
+
return true;
|
|
652
|
+
}
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Create a lazy-loaded component wrapper.
|
|
657
|
+
*
|
|
658
|
+
* The component will be loaded on first render. Use with `<Suspense>` to show
|
|
659
|
+
* a fallback while loading.
|
|
660
|
+
*
|
|
661
|
+
* @param loader - Function that returns a Promise resolving to the component
|
|
662
|
+
* @returns A component factory that loads the real component on demand
|
|
663
|
+
*
|
|
664
|
+
* @example
|
|
665
|
+
* ```tsx
|
|
666
|
+
* import { lazy, Suspense } from 'sigx';
|
|
667
|
+
*
|
|
668
|
+
* // Component will be in a separate chunk
|
|
669
|
+
* const HeavyChart = lazy(() => import('./components/HeavyChart'));
|
|
670
|
+
*
|
|
671
|
+
* // Usage
|
|
672
|
+
* <Suspense fallback={<Spinner />}>
|
|
673
|
+
* <HeavyChart data={chartData} />
|
|
674
|
+
* </Suspense>
|
|
675
|
+
*
|
|
676
|
+
* // Preload on hover
|
|
677
|
+
* <button onMouseEnter={() => HeavyChart.preload()}>
|
|
678
|
+
* Show Chart
|
|
679
|
+
* </button>
|
|
680
|
+
* ```
|
|
681
|
+
*/
|
|
682
|
+
function lazy(loader) {
|
|
683
|
+
let Component = null;
|
|
684
|
+
let promise = null;
|
|
685
|
+
let error = null;
|
|
686
|
+
let state = "pending";
|
|
687
|
+
const LazyWrapper = defineComponent((ctx) => {
|
|
688
|
+
const loadState = ctx.signal({
|
|
689
|
+
state,
|
|
690
|
+
tick: 0
|
|
691
|
+
});
|
|
692
|
+
if (!promise) promise = loader().then((mod) => {
|
|
693
|
+
Component = "default" in mod ? mod.default : mod;
|
|
694
|
+
state = "resolved";
|
|
695
|
+
loadState.state = "resolved";
|
|
696
|
+
loadState.tick++;
|
|
697
|
+
return Component;
|
|
698
|
+
}).catch((err) => {
|
|
699
|
+
error = err instanceof Error ? err : new Error(String(err));
|
|
700
|
+
state = "rejected";
|
|
701
|
+
loadState.state = "rejected";
|
|
702
|
+
loadState.tick++;
|
|
703
|
+
throw error;
|
|
704
|
+
});
|
|
705
|
+
if (state === "resolved" && Component) return () => {
|
|
706
|
+
return jsx(Component, {});
|
|
707
|
+
};
|
|
708
|
+
if (state === "rejected" && error) throw error;
|
|
709
|
+
if (!registerPendingPromise(promise)) promise.catch(() => {});
|
|
710
|
+
return () => {
|
|
711
|
+
const currentState = loadState.state;
|
|
712
|
+
loadState.tick;
|
|
713
|
+
if (currentState === "resolved" && Component) return jsx(Component, {});
|
|
714
|
+
if (currentState === "rejected" && error) throw error;
|
|
715
|
+
return null;
|
|
716
|
+
};
|
|
717
|
+
}, { name: "LazyComponent" });
|
|
718
|
+
LazyWrapper.__lazy = true;
|
|
719
|
+
LazyWrapper.preload = () => {
|
|
720
|
+
if (!promise) promise = loader().then((mod) => {
|
|
721
|
+
Component = "default" in mod ? mod.default : mod;
|
|
722
|
+
state = "resolved";
|
|
723
|
+
return Component;
|
|
724
|
+
}).catch((err) => {
|
|
725
|
+
error = err instanceof Error ? err : new Error(String(err));
|
|
726
|
+
state = "rejected";
|
|
727
|
+
throw error;
|
|
728
|
+
});
|
|
729
|
+
return promise;
|
|
730
|
+
};
|
|
731
|
+
LazyWrapper.isLoaded = () => {
|
|
732
|
+
return state === "resolved";
|
|
733
|
+
};
|
|
734
|
+
return LazyWrapper;
|
|
735
|
+
}
|
|
736
|
+
/**
|
|
737
|
+
* Suspense boundary component for handling async loading states.
|
|
738
|
+
*
|
|
739
|
+
* Wraps lazy-loaded components and shows a fallback while they load.
|
|
740
|
+
*
|
|
741
|
+
* @example
|
|
742
|
+
* ```tsx
|
|
743
|
+
* import { lazy, Suspense } from 'sigx';
|
|
744
|
+
*
|
|
745
|
+
* const LazyDashboard = lazy(() => import('./Dashboard'));
|
|
746
|
+
*
|
|
747
|
+
* // Basic usage
|
|
748
|
+
* <Suspense fallback={<div>Loading...</div>}>
|
|
749
|
+
* <LazyDashboard />
|
|
750
|
+
* </Suspense>
|
|
751
|
+
*
|
|
752
|
+
* // With spinner component
|
|
753
|
+
* <Suspense fallback={<Spinner size="large" />}>
|
|
754
|
+
* <LazyDashboard />
|
|
755
|
+
* <LazyCharts />
|
|
756
|
+
* </Suspense>
|
|
757
|
+
* ```
|
|
758
|
+
*/
|
|
759
|
+
const Suspense = defineComponent((ctx) => {
|
|
760
|
+
const { props, slots } = ctx;
|
|
761
|
+
const state = ctx.signal({
|
|
762
|
+
isReady: false,
|
|
763
|
+
pendingCount: 0
|
|
764
|
+
});
|
|
765
|
+
const boundary = {
|
|
766
|
+
pending: /* @__PURE__ */ new Set(),
|
|
767
|
+
onResolve: () => {
|
|
768
|
+
state.pendingCount = boundary.pending.size;
|
|
769
|
+
if (boundary.pending.size === 0) state.isReady = true;
|
|
770
|
+
}
|
|
771
|
+
};
|
|
772
|
+
ctx.onMount(() => {
|
|
773
|
+
if (boundary.pending.size === 0) state.isReady = true;
|
|
774
|
+
});
|
|
775
|
+
return () => {
|
|
776
|
+
state.isReady;
|
|
777
|
+
state.pendingCount;
|
|
778
|
+
const prevBoundary = currentSuspenseBoundary$1;
|
|
779
|
+
currentSuspenseBoundary$1 = boundary;
|
|
780
|
+
try {
|
|
781
|
+
const children = slots.default();
|
|
782
|
+
if (boundary.pending.size > 0) {
|
|
783
|
+
const fallback = props.fallback;
|
|
784
|
+
if (typeof fallback === "function") return fallback();
|
|
785
|
+
return fallback ?? null;
|
|
786
|
+
}
|
|
787
|
+
if (Array.isArray(children)) {
|
|
788
|
+
const filtered = children.filter((c) => c != null && c !== false && c !== true);
|
|
789
|
+
if (filtered.length === 0) return null;
|
|
790
|
+
if (filtered.length === 1) return filtered[0];
|
|
791
|
+
return filtered;
|
|
792
|
+
}
|
|
793
|
+
return children;
|
|
794
|
+
} catch (err) {
|
|
795
|
+
if (err instanceof Promise) {
|
|
796
|
+
registerPendingPromise(err);
|
|
797
|
+
const fallback = props.fallback;
|
|
798
|
+
if (typeof fallback === "function") return fallback();
|
|
799
|
+
return fallback ?? null;
|
|
800
|
+
}
|
|
801
|
+
throw err;
|
|
802
|
+
} finally {
|
|
803
|
+
currentSuspenseBoundary$1 = prevBoundary;
|
|
804
|
+
}
|
|
805
|
+
};
|
|
806
|
+
}, { name: "Suspense" });
|
|
807
|
+
/**
|
|
808
|
+
* Check if a component is a lazy-loaded component
|
|
809
|
+
*/
|
|
810
|
+
function isLazyComponent(component) {
|
|
811
|
+
return component && component.__lazy === true;
|
|
812
|
+
}
|
|
813
|
+
|
|
606
814
|
//#endregion
|
|
607
815
|
//#region ../runtime-core/src/utils/index.ts
|
|
608
816
|
var Utils = class {
|
|
@@ -913,7 +1121,6 @@ function isComponent(type) {
|
|
|
913
1121
|
}
|
|
914
1122
|
function createRenderer(options) {
|
|
915
1123
|
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;
|
|
916
|
-
let isPatching = false;
|
|
917
1124
|
let currentAppContext = null;
|
|
918
1125
|
function render$1(element, container, appContext) {
|
|
919
1126
|
if (appContext) currentAppContext = appContext;
|
|
@@ -927,6 +1134,13 @@ function createRenderer(options) {
|
|
|
927
1134
|
dom: null,
|
|
928
1135
|
text: element
|
|
929
1136
|
};
|
|
1137
|
+
else if (isComponent(element)) vnode = {
|
|
1138
|
+
type: element,
|
|
1139
|
+
props: {},
|
|
1140
|
+
key: null,
|
|
1141
|
+
children: [],
|
|
1142
|
+
dom: null
|
|
1143
|
+
};
|
|
930
1144
|
else vnode = element;
|
|
931
1145
|
if (vnode) {
|
|
932
1146
|
if (oldVNode) patch(oldVNode, vnode, container);
|
|
@@ -938,6 +1152,7 @@ function createRenderer(options) {
|
|
|
938
1152
|
}
|
|
939
1153
|
}
|
|
940
1154
|
function mount(vnode, container, before = null) {
|
|
1155
|
+
if (vnode == null || vnode === false || vnode === true) return;
|
|
941
1156
|
if (vnode.type === Text) {
|
|
942
1157
|
const node = hostCreateText(String(vnode.text));
|
|
943
1158
|
vnode.dom = node;
|
|
@@ -949,7 +1164,7 @@ function createRenderer(options) {
|
|
|
949
1164
|
const anchor = hostCreateComment("");
|
|
950
1165
|
vnode.dom = anchor;
|
|
951
1166
|
hostInsert(anchor, container, before);
|
|
952
|
-
vnode.children.forEach((child) => mount(child, container, anchor));
|
|
1167
|
+
if (vnode.children) vnode.children.forEach((child) => mount(child, container, anchor));
|
|
953
1168
|
return;
|
|
954
1169
|
}
|
|
955
1170
|
if (isComponent(vnode.type)) {
|
|
@@ -966,17 +1181,18 @@ function createRenderer(options) {
|
|
|
966
1181
|
else if (typeof vnode.props.ref === "object") vnode.props.ref.current = element;
|
|
967
1182
|
}
|
|
968
1183
|
}
|
|
969
|
-
vnode.children.forEach((child) => {
|
|
1184
|
+
if (vnode.children) vnode.children.forEach((child) => {
|
|
970
1185
|
child.parent = vnode;
|
|
971
1186
|
mount(child, element);
|
|
972
1187
|
});
|
|
973
1188
|
hostInsert(element, container, before);
|
|
974
1189
|
}
|
|
975
1190
|
function unmount(vnode, container) {
|
|
976
|
-
|
|
1191
|
+
const internalVNode = vnode;
|
|
1192
|
+
if (internalVNode._effect) internalVNode._effect.stop();
|
|
977
1193
|
if (vnode.cleanup) vnode.cleanup();
|
|
978
1194
|
if (isComponent(vnode.type)) {
|
|
979
|
-
const subTree =
|
|
1195
|
+
const subTree = internalVNode._subTree;
|
|
980
1196
|
if (subTree) unmount(subTree, container);
|
|
981
1197
|
if (vnode.dom) hostRemove(vnode.dom);
|
|
982
1198
|
if (vnode.props?.ref) {
|
|
@@ -986,7 +1202,7 @@ function createRenderer(options) {
|
|
|
986
1202
|
return;
|
|
987
1203
|
}
|
|
988
1204
|
if (vnode.type === Fragment) {
|
|
989
|
-
vnode.children.forEach((child) => unmount(child, container));
|
|
1205
|
+
if (vnode.children) vnode.children.forEach((child) => unmount(child, container));
|
|
990
1206
|
if (vnode.dom) hostRemove(vnode.dom);
|
|
991
1207
|
return;
|
|
992
1208
|
}
|
|
@@ -1006,13 +1222,15 @@ function createRenderer(options) {
|
|
|
1006
1222
|
mount(newVNode, parent, nextSibling);
|
|
1007
1223
|
return;
|
|
1008
1224
|
}
|
|
1009
|
-
|
|
1225
|
+
const oldInternal = oldVNode;
|
|
1226
|
+
const newInternal = newVNode;
|
|
1227
|
+
if (oldInternal._effect) {
|
|
1010
1228
|
newVNode.dom = oldVNode.dom;
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
const props =
|
|
1015
|
-
|
|
1229
|
+
newInternal._effect = oldInternal._effect;
|
|
1230
|
+
newInternal._subTree = oldInternal._subTree;
|
|
1231
|
+
newInternal._slots = oldInternal._slots;
|
|
1232
|
+
const props = oldInternal._componentProps;
|
|
1233
|
+
newInternal._componentProps = props;
|
|
1016
1234
|
if (props) {
|
|
1017
1235
|
const newProps$1 = newVNode.props || {};
|
|
1018
1236
|
untrack(() => {
|
|
@@ -1022,20 +1240,20 @@ function createRenderer(options) {
|
|
|
1022
1240
|
for (const key in props) if (!(key in newProps$1) && key !== "children" && key !== "key" && key !== "ref") delete props[key];
|
|
1023
1241
|
});
|
|
1024
1242
|
}
|
|
1025
|
-
const slotsRef =
|
|
1243
|
+
const slotsRef = oldInternal._slots;
|
|
1026
1244
|
const newChildren = newVNode.props?.children;
|
|
1027
1245
|
const newSlotsFromProps = newVNode.props?.slots;
|
|
1028
1246
|
if (slotsRef) {
|
|
1029
1247
|
if (newChildren !== void 0) slotsRef._children = newChildren;
|
|
1030
1248
|
if (newSlotsFromProps !== void 0) slotsRef._slotsFromProps = newSlotsFromProps;
|
|
1031
|
-
if (!
|
|
1032
|
-
|
|
1249
|
+
if (!slotsRef._isPatching) {
|
|
1250
|
+
slotsRef._isPatching = true;
|
|
1033
1251
|
try {
|
|
1034
1252
|
untrack(() => {
|
|
1035
1253
|
slotsRef._version.v++;
|
|
1036
1254
|
});
|
|
1037
1255
|
} finally {
|
|
1038
|
-
|
|
1256
|
+
slotsRef._isPatching = false;
|
|
1039
1257
|
}
|
|
1040
1258
|
}
|
|
1041
1259
|
}
|
|
@@ -1140,6 +1358,43 @@ function createRenderer(options) {
|
|
|
1140
1358
|
for (let i = beginIdx; i <= endIdx; i++) if (children[i] && isSameVNode(children[i], newChild)) return i;
|
|
1141
1359
|
return null;
|
|
1142
1360
|
}
|
|
1361
|
+
/**
|
|
1362
|
+
* Creates a props accessor that can be called with defaults or accessed directly.
|
|
1363
|
+
* After calling with defaults, direct property access uses those defaults.
|
|
1364
|
+
*/
|
|
1365
|
+
function createPropsAccessor(reactiveProps) {
|
|
1366
|
+
let defaults = {};
|
|
1367
|
+
const proxy = new Proxy(function propsAccessor() {}, {
|
|
1368
|
+
get(_, key) {
|
|
1369
|
+
if (typeof key === "symbol") return void 0;
|
|
1370
|
+
const value = reactiveProps[key];
|
|
1371
|
+
return value != null ? value : defaults[key];
|
|
1372
|
+
},
|
|
1373
|
+
apply(_, __, args) {
|
|
1374
|
+
if (args[0] && typeof args[0] === "object") defaults = {
|
|
1375
|
+
...defaults,
|
|
1376
|
+
...args[0]
|
|
1377
|
+
};
|
|
1378
|
+
return proxy;
|
|
1379
|
+
},
|
|
1380
|
+
has(_, key) {
|
|
1381
|
+
if (typeof key === "symbol") return false;
|
|
1382
|
+
return key in reactiveProps || key in defaults;
|
|
1383
|
+
},
|
|
1384
|
+
ownKeys() {
|
|
1385
|
+
return [...new Set([...Object.keys(reactiveProps), ...Object.keys(defaults)])];
|
|
1386
|
+
},
|
|
1387
|
+
getOwnPropertyDescriptor(_, key) {
|
|
1388
|
+
if (typeof key === "symbol") return void 0;
|
|
1389
|
+
if (key in reactiveProps || key in defaults) return {
|
|
1390
|
+
enumerable: true,
|
|
1391
|
+
configurable: true,
|
|
1392
|
+
writable: false
|
|
1393
|
+
};
|
|
1394
|
+
}
|
|
1395
|
+
});
|
|
1396
|
+
return proxy;
|
|
1397
|
+
}
|
|
1143
1398
|
function mountComponent(vnode, container, before, setup) {
|
|
1144
1399
|
const anchor = hostCreateComment("");
|
|
1145
1400
|
vnode.dom = anchor;
|
|
@@ -1149,9 +1404,10 @@ function createRenderer(options) {
|
|
|
1149
1404
|
let exposeCalled = false;
|
|
1150
1405
|
const { children, slots: slotsFromProps, ...propsData } = vnode.props || {};
|
|
1151
1406
|
const reactiveProps = signal(propsData);
|
|
1152
|
-
|
|
1407
|
+
const internalVNode = vnode;
|
|
1408
|
+
internalVNode._componentProps = reactiveProps;
|
|
1153
1409
|
const slots = createSlots(children, slotsFromProps);
|
|
1154
|
-
|
|
1410
|
+
internalVNode._slots = slots;
|
|
1155
1411
|
const mountHooks = [];
|
|
1156
1412
|
const cleanupHooks = [];
|
|
1157
1413
|
const parentInstance = getCurrentInstance();
|
|
@@ -1159,7 +1415,7 @@ function createRenderer(options) {
|
|
|
1159
1415
|
const ctx = {
|
|
1160
1416
|
el: container,
|
|
1161
1417
|
signal,
|
|
1162
|
-
props: reactiveProps,
|
|
1418
|
+
props: createPropsAccessor(reactiveProps),
|
|
1163
1419
|
slots,
|
|
1164
1420
|
emit: (event, ...args) => {
|
|
1165
1421
|
const handler = reactiveProps[`on${event[0].toUpperCase() + event.slice(1)}`];
|
|
@@ -1175,7 +1431,9 @@ function createRenderer(options) {
|
|
|
1175
1431
|
expose: (exposedValue) => {
|
|
1176
1432
|
exposed = exposedValue;
|
|
1177
1433
|
exposeCalled = true;
|
|
1178
|
-
}
|
|
1434
|
+
},
|
|
1435
|
+
renderFn: null,
|
|
1436
|
+
update: () => {}
|
|
1179
1437
|
};
|
|
1180
1438
|
ctx.__name = componentName;
|
|
1181
1439
|
if (currentAppContext) ctx._appContext = currentAppContext;
|
|
@@ -1199,24 +1457,31 @@ function createRenderer(options) {
|
|
|
1199
1457
|
if (typeof vnode.props.ref === "function") vnode.props.ref(refValue);
|
|
1200
1458
|
else if (vnode.props.ref && typeof vnode.props.ref === "object") vnode.props.ref.current = refValue;
|
|
1201
1459
|
}
|
|
1202
|
-
if (renderFn)
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
const
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1460
|
+
if (renderFn) {
|
|
1461
|
+
ctx.renderFn = renderFn;
|
|
1462
|
+
const componentEffect = effect(() => {
|
|
1463
|
+
const prevInstance = setCurrentInstance(ctx);
|
|
1464
|
+
try {
|
|
1465
|
+
const subTreeResult = ctx.renderFn();
|
|
1466
|
+
if (subTreeResult == null) return;
|
|
1467
|
+
const subTree = normalizeSubTree(subTreeResult);
|
|
1468
|
+
const prevSubTree = internalVNode._subTree;
|
|
1469
|
+
if (prevSubTree) {
|
|
1470
|
+
patch(prevSubTree, subTree, container);
|
|
1471
|
+
notifyComponentUpdated(currentAppContext, componentInstance);
|
|
1472
|
+
} else mount(subTree, container, anchor);
|
|
1473
|
+
internalVNode._subTree = subTree;
|
|
1474
|
+
} catch (err) {
|
|
1475
|
+
if (!handleComponentError(currentAppContext, err, componentInstance, "render")) throw err;
|
|
1476
|
+
} finally {
|
|
1477
|
+
setCurrentInstance(prevInstance);
|
|
1478
|
+
}
|
|
1479
|
+
});
|
|
1480
|
+
internalVNode._effect = componentEffect;
|
|
1481
|
+
ctx.update = () => {
|
|
1482
|
+
componentEffect();
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1220
1485
|
const mountCtx = { el: container };
|
|
1221
1486
|
mountHooks.forEach((hook) => hook(mountCtx));
|
|
1222
1487
|
notifyComponentMounted(currentAppContext, componentInstance);
|
|
@@ -1256,11 +1521,12 @@ function createRenderer(options) {
|
|
|
1256
1521
|
_children: children,
|
|
1257
1522
|
_slotsFromProps: slotsFromProps || {},
|
|
1258
1523
|
_version: versionSignal,
|
|
1524
|
+
_isPatching: false,
|
|
1259
1525
|
default: function() {
|
|
1260
1526
|
this._version.v;
|
|
1261
1527
|
const c = this._children;
|
|
1262
1528
|
const { defaultChildren } = extractNamedSlotsFromChildren(c);
|
|
1263
|
-
return defaultChildren;
|
|
1529
|
+
return defaultChildren.filter((child) => child != null && child !== false && child !== true);
|
|
1264
1530
|
}
|
|
1265
1531
|
};
|
|
1266
1532
|
return new Proxy(slotsObj, { get(target, prop) {
|
|
@@ -1279,6 +1545,8 @@ function createRenderer(options) {
|
|
|
1279
1545
|
}
|
|
1280
1546
|
/**
|
|
1281
1547
|
* Normalize render result to a VNode (wrapping arrays in Fragment)
|
|
1548
|
+
* Note: Falsy values (null, undefined, false, true) from conditional rendering
|
|
1549
|
+
* are handled by mount() which guards against them, so no filtering needed here.
|
|
1282
1550
|
*/
|
|
1283
1551
|
function normalizeSubTree(result) {
|
|
1284
1552
|
if (Array.isArray(result)) return {
|
|
@@ -1384,6 +1652,60 @@ let platformSyncProcessor = null;
|
|
|
1384
1652
|
function getPlatformSyncProcessor$1() {
|
|
1385
1653
|
return platformSyncProcessor;
|
|
1386
1654
|
}
|
|
1655
|
+
const plugins = [];
|
|
1656
|
+
/**
|
|
1657
|
+
* Get all registered plugins (internal use)
|
|
1658
|
+
*/
|
|
1659
|
+
function getComponentPlugins$1() {
|
|
1660
|
+
return plugins;
|
|
1661
|
+
}
|
|
1662
|
+
const componentRegistry = /* @__PURE__ */ new Map();
|
|
1663
|
+
/**
|
|
1664
|
+
* Define a component. Returns a JSX factory function.
|
|
1665
|
+
*
|
|
1666
|
+
* @param setup - Setup function that receives context and returns a render function
|
|
1667
|
+
* @param options - Optional configuration (e.g., name for DevTools)
|
|
1668
|
+
*
|
|
1669
|
+
* @example
|
|
1670
|
+
* ```tsx
|
|
1671
|
+
* type CardProps = DefineProp<"title", string> & DefineSlot<"header">;
|
|
1672
|
+
*
|
|
1673
|
+
* export const Card = defineComponent<CardProps>((ctx) => {
|
|
1674
|
+
* const { title } = ctx.props;
|
|
1675
|
+
* const { slots } = ctx;
|
|
1676
|
+
*
|
|
1677
|
+
* return () => (
|
|
1678
|
+
* <div class="card">
|
|
1679
|
+
* {slots.header?.() ?? <h2>{title}</h2>}
|
|
1680
|
+
* {slots.default()}
|
|
1681
|
+
* </div>
|
|
1682
|
+
* );
|
|
1683
|
+
* });
|
|
1684
|
+
* ```
|
|
1685
|
+
*/
|
|
1686
|
+
function defineComponent$1(setup, options) {
|
|
1687
|
+
const factory = function(props) {
|
|
1688
|
+
return {
|
|
1689
|
+
type: factory,
|
|
1690
|
+
props: props || {},
|
|
1691
|
+
key: props?.key || null,
|
|
1692
|
+
children: [],
|
|
1693
|
+
dom: null
|
|
1694
|
+
};
|
|
1695
|
+
};
|
|
1696
|
+
factory.__setup = setup;
|
|
1697
|
+
factory.__name = options?.name;
|
|
1698
|
+
factory.__props = null;
|
|
1699
|
+
factory.__events = null;
|
|
1700
|
+
factory.__ref = null;
|
|
1701
|
+
factory.__slots = null;
|
|
1702
|
+
componentRegistry.set(factory, {
|
|
1703
|
+
name: options?.name,
|
|
1704
|
+
setup
|
|
1705
|
+
});
|
|
1706
|
+
getComponentPlugins$1().forEach((p) => p.onDefine?.(options?.name, factory, setup));
|
|
1707
|
+
return factory;
|
|
1708
|
+
}
|
|
1387
1709
|
const Fragment$1 = Symbol.for("sigx.Fragment");
|
|
1388
1710
|
const Text$1 = Symbol.for("sigx.Text");
|
|
1389
1711
|
function normalizeChildren(children) {
|
|
@@ -1478,6 +1800,100 @@ function jsx$1(type, props, key) {
|
|
|
1478
1800
|
function jsxs$1(type, props, key) {
|
|
1479
1801
|
return jsx$1(type, props, key);
|
|
1480
1802
|
}
|
|
1803
|
+
/**
|
|
1804
|
+
* Lazy loading utilities for sigx components.
|
|
1805
|
+
*
|
|
1806
|
+
* Provides runtime-only lazy loading with no build dependencies.
|
|
1807
|
+
* Works with any bundler that supports dynamic import().
|
|
1808
|
+
*/
|
|
1809
|
+
let currentSuspenseBoundary = null;
|
|
1810
|
+
/**
|
|
1811
|
+
* Register a promise with the current Suspense boundary
|
|
1812
|
+
* @internal
|
|
1813
|
+
*/
|
|
1814
|
+
function registerPendingPromise$1(promise) {
|
|
1815
|
+
const boundary = currentSuspenseBoundary;
|
|
1816
|
+
if (boundary) {
|
|
1817
|
+
boundary.pending.add(promise);
|
|
1818
|
+
promise.finally(() => {
|
|
1819
|
+
boundary.pending.delete(promise);
|
|
1820
|
+
if (boundary.pending.size === 0) boundary.onResolve();
|
|
1821
|
+
});
|
|
1822
|
+
return true;
|
|
1823
|
+
}
|
|
1824
|
+
return false;
|
|
1825
|
+
}
|
|
1826
|
+
/**
|
|
1827
|
+
* Suspense boundary component for handling async loading states.
|
|
1828
|
+
*
|
|
1829
|
+
* Wraps lazy-loaded components and shows a fallback while they load.
|
|
1830
|
+
*
|
|
1831
|
+
* @example
|
|
1832
|
+
* ```tsx
|
|
1833
|
+
* import { lazy, Suspense } from 'sigx';
|
|
1834
|
+
*
|
|
1835
|
+
* const LazyDashboard = lazy(() => import('./Dashboard'));
|
|
1836
|
+
*
|
|
1837
|
+
* // Basic usage
|
|
1838
|
+
* <Suspense fallback={<div>Loading...</div>}>
|
|
1839
|
+
* <LazyDashboard />
|
|
1840
|
+
* </Suspense>
|
|
1841
|
+
*
|
|
1842
|
+
* // With spinner component
|
|
1843
|
+
* <Suspense fallback={<Spinner size="large" />}>
|
|
1844
|
+
* <LazyDashboard />
|
|
1845
|
+
* <LazyCharts />
|
|
1846
|
+
* </Suspense>
|
|
1847
|
+
* ```
|
|
1848
|
+
*/
|
|
1849
|
+
const Suspense$1 = defineComponent$1((ctx) => {
|
|
1850
|
+
const { props, slots } = ctx;
|
|
1851
|
+
const state = ctx.signal({
|
|
1852
|
+
isReady: false,
|
|
1853
|
+
pendingCount: 0
|
|
1854
|
+
});
|
|
1855
|
+
const boundary = {
|
|
1856
|
+
pending: /* @__PURE__ */ new Set(),
|
|
1857
|
+
onResolve: () => {
|
|
1858
|
+
state.pendingCount = boundary.pending.size;
|
|
1859
|
+
if (boundary.pending.size === 0) state.isReady = true;
|
|
1860
|
+
}
|
|
1861
|
+
};
|
|
1862
|
+
ctx.onMount(() => {
|
|
1863
|
+
if (boundary.pending.size === 0) state.isReady = true;
|
|
1864
|
+
});
|
|
1865
|
+
return () => {
|
|
1866
|
+
state.isReady;
|
|
1867
|
+
state.pendingCount;
|
|
1868
|
+
const prevBoundary = currentSuspenseBoundary;
|
|
1869
|
+
currentSuspenseBoundary = boundary;
|
|
1870
|
+
try {
|
|
1871
|
+
const children = slots.default();
|
|
1872
|
+
if (boundary.pending.size > 0) {
|
|
1873
|
+
const fallback = props.fallback;
|
|
1874
|
+
if (typeof fallback === "function") return fallback();
|
|
1875
|
+
return fallback ?? null;
|
|
1876
|
+
}
|
|
1877
|
+
if (Array.isArray(children)) {
|
|
1878
|
+
const filtered = children.filter((c) => c != null && c !== false && c !== true);
|
|
1879
|
+
if (filtered.length === 0) return null;
|
|
1880
|
+
if (filtered.length === 1) return filtered[0];
|
|
1881
|
+
return filtered;
|
|
1882
|
+
}
|
|
1883
|
+
return children;
|
|
1884
|
+
} catch (err) {
|
|
1885
|
+
if (err instanceof Promise) {
|
|
1886
|
+
registerPendingPromise$1(err);
|
|
1887
|
+
const fallback = props.fallback;
|
|
1888
|
+
if (typeof fallback === "function") return fallback();
|
|
1889
|
+
return fallback ?? null;
|
|
1890
|
+
}
|
|
1891
|
+
throw err;
|
|
1892
|
+
} finally {
|
|
1893
|
+
currentSuspenseBoundary = prevBoundary;
|
|
1894
|
+
}
|
|
1895
|
+
};
|
|
1896
|
+
}, { name: "Suspense" });
|
|
1481
1897
|
|
|
1482
1898
|
//#endregion
|
|
1483
1899
|
//#region ../runtime-terminal/src/components/Input.tsx
|
|
@@ -2024,5 +2440,5 @@ const terminalMount = (component, options, appContext) => {
|
|
|
2024
2440
|
setDefaultMount(terminalMount);
|
|
2025
2441
|
|
|
2026
2442
|
//#endregion
|
|
2027
|
-
export { AppContextKey, Button, Checkbox, Fragment, Input, InstanceLifetimes, ProgressBar, Select, SubscriptionHandler, Text, Utils, batch, createApp, createPropsProxy, createRenderer, createTopic, defineApp, defineComponent, defineFactory, defineInjectable, defineProvide, defineStore, detectAccess, effect, effectScope, exitTerminal, focus, focusNext, focusPrev, focusState, getComponentMeta, getComponentPlugins, getCurrentInstance, getDefaultMount, getPlatformSyncProcessor, guid, handleComponentError, inject, injectApp, jsx, jsxDEV, jsxs, mountTerminal, notifyComponentCreated, notifyComponentMounted, notifyComponentUnmounted, notifyComponentUpdated, onCleanup, onKey, onMount, provide, registerComponentPlugin, registerFocusable, render, renderNodeToLines, renderTerminal, setCurrentInstance, setDefaultMount, setPlatformSyncProcessor, signal, terminalMount, toSubscriber, unregisterFocusable, untrack, valueOf, watch };
|
|
2443
|
+
export { AppContextKey, Button, Checkbox, Fragment, Input, InstanceLifetimes, ProgressBar, Select, SubscriptionHandler, Suspense, Text, Utils, batch, createApp, createPropsProxy, createRenderer, 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, notifyComponentCreated, notifyComponentMounted, notifyComponentUnmounted, notifyComponentUpdated, onCleanup, onKey, onMount, provide, registerComponentPlugin, registerFocusable, registerPendingPromise, render, renderNodeToLines, renderTerminal, setCurrentInstance, setDefaultMount, setPlatformSyncProcessor, signal, terminalMount, toSubscriber, unregisterFocusable, untrack, valueOf, watch };
|
|
2028
2444
|
//# sourceMappingURL=index.js.map
|