ilha 0.11.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -331,7 +331,7 @@ Both the user-supplied cleanup function (if any) and the signal abort fire when
331
331
 
332
332
  ### `.onMount(fn)`
333
333
 
334
- Runs once after the island is mounted into the DOM. Receives `{ state, derived, input, host, hydrated }` where `hydrated` is `true` when the island was mounted over existing SSR content. Optionally returns a cleanup function called on unmount.
334
+ Runs once after the island is mounted into the DOM. **Client-only** — SSR never invokes it (matching `.on()` and `.effect()`), so server-rendered markup must not depend on onMount side effects. Receives `{ state, derived, input, host, hydrated }` where `hydrated` is `true` when the island was mounted over existing SSR content. Optionally returns a cleanup function called on unmount.
335
335
 
336
336
  ```ts
337
337
  ilha
@@ -538,7 +538,8 @@ Use `await island(props)` instead when asynchronous derived values must settle b
538
538
  ```ts
539
539
  MyIsland.toString(); // always sync
540
540
  MyIsland.toString({ name: "Ilha" }); // with props
541
- await MyIsland({ name: "Ilha" }); // async — awaits derived
541
+ await MyIsland.toStringAsync({ name: "Ilha" }); // async SSR — awaits async derived values
542
+ await MyIsland({ name: "Ilha" }); // callable async form (also used for JSX/html slot composition)
542
543
  ```
543
544
 
544
545
  ---
@@ -666,6 +667,8 @@ theme("dark"); // → sets to "dark"
666
667
  Safe to call in both SSR and browser environments.
667
668
 
668
669
  > **`signal()` vs `context()`** — both return the same accessor shape and can be used with `bind:` template syntax. Use `signal()` for one-off shared state where you'd hold the reference yourself; use `context()` when you want a name-keyed registry so the same signal can be looked up from anywhere by string key.
670
+ >
671
+ > **SSR caveat** — `context()` is process-global, not request-scoped. It is safe to read in SSR **only for app-wide singletons** (theme, locale, feature flags). Per-request state (current user, session) must not live in `context()`: concurrent SSR requests would leak it across requests. Pass per-request data through island props / loaders or use `@ilha/router`'s request-scope instead.
669
672
 
670
673
  ---
671
674
 
@@ -178,6 +178,12 @@ interface HydratableOptions {
178
178
  interface Island<TInput = Record<string, unknown>, _TStateMap extends Record<string, unknown> = Record<string, unknown>> {
179
179
  (props?: Partial<TInput>): string | Promise<string>;
180
180
  toString(props?: Partial<TInput>): string;
181
+ /**
182
+ * Async SSR: renders the island and awaits async `.derived()` values before
183
+ * returning the HTML string. Always returns a Promise — prefer this over
184
+ * `await island(props)` when you need the async SSR form by name.
185
+ */
186
+ toStringAsync(props?: Partial<TInput>): Promise<string>;
181
187
  mount(host: Element, props?: Partial<TInput>): () => void;
182
188
  hydratable(props: Partial<TInput>, options: HydratableOptions): Promise<string>;
183
189
  key(key: string): KeyedIsland<TInput>;
@@ -408,6 +414,7 @@ declare const ilha: RootBuilder & DirectIslandFactory & {
408
414
  };
409
415
  signal: typeof ilhaSignal;
410
416
  computed: typeof ilhaComputed;
417
+ morph: typeof morph;
411
418
  batch: typeof batch;
412
419
  untrack: typeof untrack;
413
420
  onUncaughtError: typeof onUncaughtError;
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { A as StreamFnContext, B as ilhaEffect, C as NativeEventModifier, D as SignalSetter, E as SignalAccessor, F as css, G as raw, H as morph, I as from, K as untrack, L as html, M as __ilhaJsxSlot, N as batch, O as SignalWriter, P as context, R as ilha, S as NativeEventHandler, T as RawHtml, U as mount, V as ilhaSignal, W as onUncaughtError, _ as IslandState, a as EffectContext, b as MountResult, c as ExternalSignal, d as HydratableOptions, f as ISLAND_MOUNT_HANDLES, g as IslandDerived, h as IslandActions, i as DerivedValue, j as __ilhaJsxEvent, k as StreamFn, l as HandlerContext, m as Island, n as ActionContext, o as ErrorContext, p as ISLAND_MOUNT_INTERNAL, r as DerivedAccessor, s as ErrorSource, t as ActionAccessor, u as HandlerContextFor, v as KeyedIsland, w as OnMountContext, x as NativeEventContext, y as MountOptions, z as ilhaComputed } from "./index-Cx35Xugv.js";
2
- export { ActionAccessor, ActionContext, DerivedAccessor, DerivedValue, EffectContext, ErrorContext, ErrorSource, ExternalSignal, HandlerContext, HandlerContextFor, HydratableOptions, ISLAND_MOUNT_HANDLES, ISLAND_MOUNT_INTERNAL, Island, IslandActions, IslandDerived, IslandState, KeyedIsland, MountOptions, MountResult, NativeEventContext, NativeEventHandler, NativeEventModifier, OnMountContext, RawHtml, SignalAccessor, SignalSetter, SignalWriter, StreamFn, StreamFnContext, __ilhaJsxEvent, __ilhaJsxSlot, batch, ilhaComputed as computed, context, css, ilha as default, ilhaEffect as effect, from, html, ilhaSignal, ilhaSignal as signal, morph, mount, onUncaughtError, raw, untrack };
1
+ import { A as StreamFnContext, B as ilhaEffect, C as NativeEventModifier, D as SignalSetter, E as SignalAccessor, F as css, G as raw, H as morph, I as from, K as untrack, L as html, M as __ilhaJsxSlot, N as batch, O as SignalWriter, P as context, R as ilha, S as NativeEventHandler, T as RawHtml, U as mount, V as ilhaSignal, W as onUncaughtError, _ as IslandState, a as EffectContext, b as MountResult, c as ExternalSignal, d as HydratableOptions, f as ISLAND_MOUNT_HANDLES, g as IslandDerived, h as IslandActions, i as DerivedValue, j as __ilhaJsxEvent, k as StreamFn, l as HandlerContext, m as Island, n as ActionContext, o as ErrorContext, p as ISLAND_MOUNT_INTERNAL, r as DerivedAccessor, s as ErrorSource, t as ActionAccessor, u as HandlerContextFor, v as KeyedIsland, w as OnMountContext, x as NativeEventContext, y as MountOptions, z as ilhaComputed } from "./index-DnoM0M8S.js";
2
+ export { ActionAccessor, ActionContext, DerivedAccessor, DerivedValue, EffectContext, ErrorContext, ErrorSource, ExternalSignal, HandlerContext, HandlerContextFor, HydratableOptions, ISLAND_MOUNT_HANDLES, ISLAND_MOUNT_INTERNAL, Island, IslandActions, IslandDerived, IslandState, KeyedIsland, MountOptions, MountResult, NativeEventContext, NativeEventHandler, NativeEventModifier, OnMountContext, RawHtml, SignalAccessor, SignalSetter, SignalWriter, StreamFn, StreamFnContext, __ilhaJsxEvent, __ilhaJsxSlot, batch, ilhaComputed as computed, context, css, ilhaEffect as effect, from, html, ilha, ilhaSignal, ilhaSignal as signal, morph, mount, onUncaughtError, raw, untrack };
package/dist/index.js CHANGED
@@ -1690,8 +1690,10 @@ var IlhaBuilder = class IlhaBuilder {
1690
1690
  input(initialOrSchema) {
1691
1691
  let schema = null;
1692
1692
  let defaultInput = null;
1693
- if (initialOrSchema !== void 0) if (isStandardSchema(initialOrSchema)) schema = initialOrSchema;
1694
- else defaultInput = initialOrSchema;
1693
+ if (initialOrSchema !== void 0) {
1694
+ if (isStandardSchema(initialOrSchema)) schema = initialOrSchema;
1695
+ else defaultInput = initialOrSchema;
1696
+ }
1695
1697
  return new IlhaBuilder({
1696
1698
  schema,
1697
1699
  defaultInput,
@@ -1912,72 +1914,6 @@ var IlhaBuilder = class IlhaBuilder {
1912
1914
  lookup
1913
1915
  };
1914
1916
  }
1915
- /** Detached host for SSR setup hooks; must not be `{}` (Areia/components call host.matches). */
1916
- function createSsrOnMountHost() {
1917
- if (typeof document !== "undefined") return document.createElement("div");
1918
- const stub = {
1919
- matches: () => false,
1920
- querySelector: () => null,
1921
- querySelectorAll: () => [],
1922
- setAttribute: () => {},
1923
- getAttribute: () => null,
1924
- removeAttribute: () => {},
1925
- appendChild: () => stub
1926
- };
1927
- return stub;
1928
- }
1929
- /** Run .onMount() before top-level SSR only (seed module/external state from `input`). */
1930
- function runOnMountForRender({ input, state, derived, action }) {
1931
- if (onMounts.length === 0) return;
1932
- if (currentRenderCtx()) return;
1933
- const host = createSsrOnMountHost();
1934
- const controller = new AbortController();
1935
- const ssrCleanups = [];
1936
- for (const entry of onMounts) {
1937
- const prevSub = setActiveSub(void 0);
1938
- let userCleanup;
1939
- try {
1940
- userCleanup = entry.fn({
1941
- state,
1942
- derived,
1943
- action,
1944
- input,
1945
- host,
1946
- hydrated: false,
1947
- signal: controller.signal
1948
- });
1949
- } catch (err) {
1950
- const error = err instanceof Error ? err : new Error(String(err));
1951
- if (onErrors.length === 0) {
1952
- if (!reportToGlobal(error, "mount")) console.error(error);
1953
- } else for (const oe of onErrors) try {
1954
- oe.fn({
1955
- error,
1956
- source: "mount",
1957
- state,
1958
- derived,
1959
- action,
1960
- input,
1961
- host
1962
- });
1963
- } catch (handlerErr) {
1964
- console.error(handlerErr);
1965
- }
1966
- } finally {
1967
- setActiveSub(prevSub);
1968
- }
1969
- if (typeof userCleanup === "function") ssrCleanups.push(userCleanup);
1970
- }
1971
- controller.abort();
1972
- for (const teardown of ssrCleanups.reverse()) try {
1973
- teardown();
1974
- } catch (err) {
1975
- const error = err instanceof Error ? err : new Error(String(err));
1976
- if (onErrors.length === 0) {
1977
- if (!reportToGlobal(error, "mount")) console.error(error);
1978
- }
1979
- }
1980
- }
1981
1917
  function renderToString(props, sync = false, streamOut, eventsOut, stateOverride, forceAsyncChildren = false) {
1982
1918
  const input = resolveInput(props);
1983
1919
  const state = buildSignalState(input, stateOverride);
@@ -2053,12 +1989,6 @@ var IlhaBuilder = class IlhaBuilder {
2053
1989
  error: void 0
2054
1990
  };
2055
1991
  const derived = buildDerivedAccessors(envelopes);
2056
- if (!currentRenderCtx()) runOnMountForRender({
2057
- input,
2058
- state,
2059
- derived,
2060
- action
2061
- });
2062
1992
  const prevSub = setActiveSub(void 0);
2063
1993
  try {
2064
1994
  const { html, events } = renderWithCtx({
@@ -2100,12 +2030,6 @@ var IlhaBuilder = class IlhaBuilder {
2100
2030
  const envelopes = {};
2101
2031
  for (const r of resolved) envelopes[r.key] = r.envelope;
2102
2032
  const derived = buildDerivedAccessors(envelopes);
2103
- if (!currentRenderCtx()) runOnMountForRender({
2104
- input,
2105
- state,
2106
- derived,
2107
- action
2108
- });
2109
2033
  const prevSub = setActiveSub(void 0);
2110
2034
  try {
2111
2035
  const { html, events } = await renderWithCtx({
@@ -2803,6 +2727,7 @@ var IlhaBuilder = class IlhaBuilder {
2803
2727
  return renderToString(props);
2804
2728
  });
2805
2729
  island.toString = (props) => renderToString(props, true);
2730
+ island.toStringAsync = (props) => Promise.resolve(renderToString(props, false));
2806
2731
  island.mount = (host, props) => mountIsland(host, props);
2807
2732
  island[ISLAND_MOUNT_INTERNAL] = (host, props) => mountIslandInternal(host, props);
2808
2733
  island[ISLAND_SLOT_TAG] = configuredSlotTag;
@@ -3067,6 +2992,7 @@ const ilha = Object.assign(callableRoot, {
3067
2992
  context: ilhaContext,
3068
2993
  signal: ilhaSignal,
3069
2994
  computed: ilhaComputed,
2995
+ morph,
3070
2996
  batch,
3071
2997
  untrack,
3072
2998
  onUncaughtError
@@ -3123,4 +3049,4 @@ const from = ilhaFrom;
3123
3049
  const context = ilhaContext;
3124
3050
 
3125
3051
  //#endregion
3126
- export { ISLAND_MOUNT_HANDLES, ISLAND_MOUNT_INTERNAL, __ilhaJsxEvent, __ilhaJsxSlot, batch, ilhaComputed as computed, context, css, ilha as default, ilhaEffect as effect, from, html, ilhaSignal, ilhaSignal as signal, morph, mount, onUncaughtError, raw, untrack };
3052
+ export { ISLAND_MOUNT_HANDLES, ISLAND_MOUNT_INTERNAL, __ilhaJsxEvent, __ilhaJsxSlot, batch, ilhaComputed as computed, context, css, ilhaEffect as effect, from, html, ilha, ilhaSignal, ilhaSignal as signal, morph, mount, onUncaughtError, raw, untrack };
@@ -1,2 +1,2 @@
1
- import { a as JSX, r as jsxDEV, t as Fragment } from "./jsx-runtime-B-viVOB1.js";
1
+ import { a as JSX, r as jsxDEV, t as Fragment } from "./jsx-runtime-DMkplizR.js";
2
2
  export { Fragment, type JSX, jsxDEV };
@@ -1,4 +1,4 @@
1
- import { C as NativeEventModifier, E as SignalAccessor, O as SignalWriter, S as NativeEventHandler, T as RawHtml } from "./index-Cx35Xugv.js";
1
+ import { C as NativeEventModifier, E as SignalAccessor, O as SignalWriter, S as NativeEventHandler, T as RawHtml } from "./index-DnoM0M8S.js";
2
2
  //#region src/jsx-types.d.ts
3
3
  declare namespace JSX {
4
4
  export type Child = unknown;
@@ -1,2 +1,2 @@
1
- import { a as JSX, i as jsxs, n as jsx, r as jsxDEV, t as Fragment } from "./jsx-runtime-B-viVOB1.js";
1
+ import { a as JSX, i as jsxs, n as jsx, r as jsxDEV, t as Fragment } from "./jsx-runtime-DMkplizR.js";
2
2
  export { Fragment, type JSX, jsx, jsxDEV, jsxs };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ilha",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "A tiny, framework-free island architecture library",
5
5
  "keywords": [
6
6
  "framework-free",