@sigx/terminal 0.1.24 → 0.1.26

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
@@ -665,6 +665,59 @@ function component(setup, options) {
665
665
  getComponentPlugins().forEach((p) => p.onDefine?.(options?.name, factory, setup));
666
666
  return factory;
667
667
  }
668
+ var SigxError = class extends Error {
669
+ constructor(message, options) {
670
+ super(message);
671
+ this.name = "SigxError";
672
+ this.code = options.code;
673
+ this.suggestion = options.suggestion;
674
+ if (options.cause) this.cause = options.cause;
675
+ }
676
+ };
677
+ const SigxErrorCode = {
678
+ NO_MOUNT_FUNCTION: "SIGX001",
679
+ RENDER_TARGET_NOT_FOUND: "SIGX100",
680
+ MOUNT_TARGET_NOT_FOUND: "SIGX101",
681
+ ASYNC_SETUP_CLIENT: "SIGX102",
682
+ PROVIDE_OUTSIDE_SETUP: "SIGX200",
683
+ PROVIDE_INVALID_INJECTABLE: "SIGX201"
684
+ };
685
+ function noMountFunctionError() {
686
+ return new SigxError("No mount function provided and no default mount function set.", {
687
+ code: SigxErrorCode.NO_MOUNT_FUNCTION,
688
+ suggestion: "Either pass a mount function to app.mount(), or import a platform package (e.g., @sigx/runtime-dom or @sigx/runtime-terminal) that sets the default."
689
+ });
690
+ }
691
+ function renderTargetNotFoundError(selector) {
692
+ return new SigxError(`Render target "${selector}" not found.`, {
693
+ code: SigxErrorCode.RENDER_TARGET_NOT_FOUND,
694
+ suggestion: `Make sure the element exists in your HTML: <div id="${selector.replace(/^#/, "")}"></div>`
695
+ });
696
+ }
697
+ function mountTargetNotFoundError(selector) {
698
+ return new SigxError(`Mount target "${selector}" not found.`, {
699
+ code: SigxErrorCode.MOUNT_TARGET_NOT_FOUND,
700
+ suggestion: `Make sure the element exists in your HTML: <div id="${selector.replace(/^#/, "")}"></div>`
701
+ });
702
+ }
703
+ function asyncSetupClientError(componentName) {
704
+ return new SigxError(`Async setup in component "${componentName}" is only supported during SSR.`, {
705
+ code: SigxErrorCode.ASYNC_SETUP_CLIENT,
706
+ suggestion: "On the client, use pre-loaded data from hydration or fetch in onMounted."
707
+ });
708
+ }
709
+ function provideOutsideSetupError() {
710
+ return new SigxError("defineProvide must be called inside a component setup function.", {
711
+ code: SigxErrorCode.PROVIDE_OUTSIDE_SETUP,
712
+ suggestion: "Move the defineProvide() call inside your component's setup function, or use app.defineProvide() at the app level."
713
+ });
714
+ }
715
+ function provideInvalidInjectableError() {
716
+ return new SigxError("defineProvide must be called with a function created by defineInjectable.", {
717
+ code: SigxErrorCode.PROVIDE_INVALID_INJECTABLE,
718
+ suggestion: "Create an injectable first:\n const useMyService = defineInjectable(() => new MyService());\n defineProvide(useMyService);"
719
+ });
720
+ }
668
721
  var globalInstances = /* @__PURE__ */ new Map();
669
722
  var appContextToken = Symbol("sigx:appContext");
670
723
  function lookupProvided(token) {
@@ -678,9 +731,10 @@ function lookupProvided(token) {
678
731
  }
679
732
  function provideAtComponent(token, value) {
680
733
  const ctx = getCurrentInstance();
681
- if (!ctx) throw new Error("defineProvide must be called inside a component setup function");
682
- if (!ctx.provides) ctx.provides = /* @__PURE__ */ new Map();
683
- ctx.provides.set(token, value);
734
+ if (!ctx) throw provideOutsideSetupError();
735
+ const node = ctx;
736
+ if (!node.provides) node.provides = /* @__PURE__ */ new Map();
737
+ node.provides.set(token, value);
684
738
  }
685
739
  function defineInjectable(factory) {
686
740
  const token = Symbol();
@@ -697,7 +751,7 @@ function defineInjectable(factory) {
697
751
  function defineProvide(useFn, factory) {
698
752
  const actualFactory = factory ?? useFn._factory;
699
753
  const token = useFn._token;
700
- if (!actualFactory || !token) throw new Error("defineProvide must be called with a function created by defineInjectable");
754
+ if (!actualFactory || !token) throw provideInvalidInjectableError();
701
755
  const instance = actualFactory();
702
756
  provideAtComponent(token, instance);
703
757
  return instance;
@@ -709,9 +763,10 @@ function getAppContextToken() {
709
763
  return appContextToken;
710
764
  }
711
765
  function provideAppContext(ctx, appContext) {
712
- if (!ctx.provides) ctx.provides = /* @__PURE__ */ new Map();
713
- ctx.provides.set(appContextToken, appContext);
714
- if (appContext.provides) for (const [token, value] of appContext.provides) ctx.provides.set(token, value);
766
+ const node = ctx;
767
+ if (!node.provides) node.provides = /* @__PURE__ */ new Map();
768
+ node.provides.set(appContextToken, appContext);
769
+ if (appContext.provides) for (const [token, value] of appContext.provides) node.provides.set(token, value);
715
770
  }
716
771
  const __DIRECTIVE__ = Symbol.for("sigx.directive");
717
772
  function defineDirective(definition) {
@@ -754,7 +809,7 @@ function defineApp(rootComponent) {
754
809
  defineProvide(useFn, factory) {
755
810
  const actualFactory = factory ?? useFn._factory;
756
811
  const token = useFn._token;
757
- if (!actualFactory || !token) throw new Error("defineProvide must be called with a function created by defineInjectable");
812
+ if (!actualFactory || !token) throw provideInvalidInjectableError();
758
813
  const instance = actualFactory();
759
814
  context.provides.set(token, instance);
760
815
  return instance;
@@ -777,7 +832,7 @@ function defineApp(rootComponent) {
777
832
  return app;
778
833
  }
779
834
  const mountFn = renderFn ?? defaultMountFn;
780
- if (!mountFn) throw new Error("No mount function provided and no default mount function set. Either pass a mount function to app.mount(), or import a platform package (e.g., @sigx/runtime-dom or @sigx/runtime-terminal) that sets the default.");
835
+ if (!mountFn) throw noMountFunctionError();
781
836
  container = target;
782
837
  isMounted = true;
783
838
  const result = mountFn(rootComponent, target, context);
@@ -903,10 +958,60 @@ function isComponent(type) {
903
958
  }
904
959
  const Fragment = Symbol.for("sigx.Fragment");
905
960
  const Text = Symbol.for("sigx.Text");
961
+ const Comment = Symbol.for("sigx.Comment");
906
962
  function normalizeChildren(children) {
907
963
  if (children == null || children === false || children === true) return [];
908
964
  if (isComputed(children)) return normalizeChildren(children.value);
909
- if (Array.isArray(children)) return children.flatMap((c) => normalizeChildren(c));
965
+ if (Array.isArray(children)) return children.map((c) => {
966
+ if (c == null || c === false || c === true) return {
967
+ type: Comment,
968
+ props: {},
969
+ key: null,
970
+ children: [],
971
+ dom: null
972
+ };
973
+ if (isComputed(c)) return normalizeChildren(c.value)[0] ?? {
974
+ type: Comment,
975
+ props: {},
976
+ key: null,
977
+ children: [],
978
+ dom: null
979
+ };
980
+ if (typeof c === "string" || typeof c === "number") return {
981
+ type: Text,
982
+ props: {},
983
+ key: null,
984
+ children: [],
985
+ dom: null,
986
+ text: c
987
+ };
988
+ if (Array.isArray(c)) {
989
+ const nested = normalizeChildren(c);
990
+ if (nested.length === 0) return {
991
+ type: Comment,
992
+ props: {},
993
+ key: null,
994
+ children: [],
995
+ dom: null
996
+ };
997
+ if (nested.length === 1) return nested[0];
998
+ return {
999
+ type: Fragment,
1000
+ props: {},
1001
+ key: null,
1002
+ children: nested,
1003
+ dom: null
1004
+ };
1005
+ }
1006
+ if (c.type) return c;
1007
+ return {
1008
+ type: Comment,
1009
+ props: {},
1010
+ key: null,
1011
+ children: [],
1012
+ dom: null
1013
+ };
1014
+ });
910
1015
  if (typeof children === "string" || typeof children === "number") return [{
911
1016
  type: Text,
912
1017
  props: {},
@@ -1045,6 +1150,22 @@ function lazy(loader) {
1045
1150
  state,
1046
1151
  tick: 0
1047
1152
  });
1153
+ function renderInner(Comp) {
1154
+ const fwdProps = { ...ctx.props };
1155
+ const defaultContent = ctx.slots.default();
1156
+ if (defaultContent.length > 0) fwdProps.children = defaultContent;
1157
+ const slotsFromProps = ctx.slots._slotsFromProps;
1158
+ if (slotsFromProps) {
1159
+ const namedSlots = {};
1160
+ let hasNamed = false;
1161
+ for (const key of Object.keys(slotsFromProps)) {
1162
+ namedSlots[key] = slotsFromProps[key];
1163
+ hasNamed = true;
1164
+ }
1165
+ if (hasNamed) fwdProps.slots = namedSlots;
1166
+ }
1167
+ return jsx(Comp, fwdProps);
1168
+ }
1048
1169
  if (!promise) promise = loader().then((mod) => {
1049
1170
  Component = "default" in mod ? mod.default : mod;
1050
1171
  state = "resolved";
@@ -1073,15 +1194,13 @@ function lazy(loader) {
1073
1194
  loadState.tick++;
1074
1195
  });
1075
1196
  });
1076
- if (state === "resolved" && Component) return () => {
1077
- return jsx(Component, {});
1078
- };
1197
+ if (state === "resolved" && Component) return () => renderInner(Component);
1079
1198
  if (state === "rejected" && error) throw error;
1080
1199
  if (!registerPendingPromise(promise)) promise.catch(() => {});
1081
1200
  return () => {
1082
1201
  const currentState = loadState.state;
1083
1202
  loadState.tick;
1084
- if (currentState === "resolved" && Component) return jsx(Component, {});
1203
+ if (currentState === "resolved" && Component) return renderInner(Component);
1085
1204
  if (currentState === "rejected" && error) throw error;
1086
1205
  return null;
1087
1206
  };
@@ -1157,6 +1276,25 @@ const Suspense = component((ctx) => {
1157
1276
  function isLazyComponent(component) {
1158
1277
  return component && component.__lazy === true;
1159
1278
  }
1279
+ function useAsync(loader) {
1280
+ const state = signal({
1281
+ value: null,
1282
+ loading: true,
1283
+ error: null
1284
+ });
1285
+ loader().then((val) => {
1286
+ batch(() => {
1287
+ state.value = val;
1288
+ state.loading = false;
1289
+ });
1290
+ }).catch((err) => {
1291
+ batch(() => {
1292
+ state.error = err instanceof Error ? err : new Error(String(err));
1293
+ state.loading = false;
1294
+ });
1295
+ });
1296
+ return state;
1297
+ }
1160
1298
  const ErrorBoundary = component((ctx) => {
1161
1299
  const { fallback } = ctx.props;
1162
1300
  const { slots } = ctx;
@@ -1256,7 +1394,7 @@ function defineFactory(setup, _lifetime, _typeIdentifier) {
1256
1394
  const dispose = () => {
1257
1395
  deactivations.forEach((d) => d());
1258
1396
  subscriptions.unsubscribe();
1259
- result.dispose?.();
1397
+ if (result && typeof result === "object" && "dispose" in result && typeof result.dispose === "function") result.dispose();
1260
1398
  };
1261
1399
  if (customDispose) customDispose(dispose);
1262
1400
  else try {
@@ -1487,6 +1625,12 @@ function createRenderer(options) {
1487
1625
  hostInsert(node, container, before);
1488
1626
  return;
1489
1627
  }
1628
+ if (vnode.type === Comment) {
1629
+ const node = hostCreateComment("");
1630
+ vnode.dom = node;
1631
+ hostInsert(node, container, before);
1632
+ return;
1633
+ }
1490
1634
  if (vnode.type === Fragment) {
1491
1635
  const anchor = hostCreateComment("");
1492
1636
  vnode.dom = anchor;
@@ -1539,6 +1683,10 @@ function createRenderer(options) {
1539
1683
  if (vnode.dom) hostRemove(vnode.dom);
1540
1684
  return;
1541
1685
  }
1686
+ if (vnode.type === Comment) {
1687
+ if (vnode.dom) hostRemove(vnode.dom);
1688
+ return;
1689
+ }
1542
1690
  if (vnode.props?.ref) untrack(() => {
1543
1691
  if (typeof vnode.props.ref === "function") vnode.props.ref(null);
1544
1692
  else if (vnode.props.ref && typeof vnode.props.ref === "object") vnode.props.ref.current = null;
@@ -1618,6 +1766,10 @@ function createRenderer(options) {
1618
1766
  if (oldVNode.text !== newVNode.text) hostSetText(newVNode.dom, String(newVNode.text));
1619
1767
  return;
1620
1768
  }
1769
+ if (newVNode.type === Comment) {
1770
+ newVNode.dom = oldVNode.dom;
1771
+ return;
1772
+ }
1621
1773
  if (newVNode.type === Fragment) {
1622
1774
  patchChildren(oldVNode, newVNode, container, false);
1623
1775
  return;
@@ -1798,7 +1950,7 @@ function createRenderer(options) {
1798
1950
  let renderFn;
1799
1951
  try {
1800
1952
  const setupResult = setup(ctx);
1801
- if (setupResult && typeof setupResult.then === "function") throw new Error(`Async setup in component "${componentName}" is only supported during SSR. On the client, use pre-loaded data from hydration or fetch in onMounted.`);
1953
+ if (setupResult && typeof setupResult.then === "function") throw asyncSetupClientError(componentName ?? "anonymous");
1802
1954
  renderFn = setupResult;
1803
1955
  notifyComponentCreated(currentAppContext, componentInstance);
1804
1956
  createdHooks.forEach((hook) => hook());
@@ -1853,7 +2005,7 @@ function createRenderer(options) {
1853
2005
  };
1854
2006
  }
1855
2007
  const mountCtx = { el: container };
1856
- mountHooks.forEach((hook) => hook(mountCtx));
2008
+ untrack(() => mountHooks.forEach((hook) => hook(mountCtx)));
1857
2009
  notifyComponentMounted(currentAppContext, componentInstance);
1858
2010
  vnode.cleanup = () => {
1859
2011
  notifyComponentUnmounted(currentAppContext, componentInstance);
@@ -2425,6 +2577,6 @@ const terminalMount = (component, options, appContext) => {
2425
2577
  };
2426
2578
  };
2427
2579
  setDefaultMount(terminalMount);
2428
- export { Button, CLIENT_DIRECTIVES, CLIENT_DIRECTIVE_PREFIX, Checkbox, ComputedSymbol, ErrorBoundary, Fragment, Input, InstanceLifetimes, ProgressBar, Select, SubscriptionHandler, Suspense, Text, Utils, 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, mountTerminal, onCreated, onKey, onMounted, onUnmounted, onUpdated, registerFocusable, render, renderNodeToLines, renderTerminal, signal, terminalMount, toRaw, toSubscriber, unregisterFocusable, untrack, useAppContext, watch };
2580
+ 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 };
2429
2581
 
2430
2582
  //# sourceMappingURL=index.js.map