@getforma/core 1.2.0 → 1.4.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.
Files changed (41) hide show
  1. package/dist/{chunk-YRNYOZF3.js → chunk-AJP4OVCN.js} +27 -7
  2. package/dist/chunk-AJP4OVCN.js.map +1 -0
  3. package/dist/{chunk-E3FV2VSU.cjs → chunk-FBM7V4NE.cjs} +27 -6
  4. package/dist/chunk-FBM7V4NE.cjs.map +1 -0
  5. package/dist/forma-runtime-csp.js +178 -79
  6. package/dist/forma-runtime.js +178 -79
  7. package/dist/formajs-runtime-hardened.global.js +178 -79
  8. package/dist/formajs-runtime-hardened.global.js.map +1 -1
  9. package/dist/formajs-runtime.global.js +178 -79
  10. package/dist/formajs-runtime.global.js.map +1 -1
  11. package/dist/formajs.global.js +69 -9
  12. package/dist/formajs.global.js.map +1 -1
  13. package/dist/index.cjs +59 -16
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.cts +14 -1
  16. package/dist/index.d.ts +14 -1
  17. package/dist/index.js +46 -7
  18. package/dist/index.js.map +1 -1
  19. package/dist/runtime-hardened.cjs +178 -79
  20. package/dist/runtime-hardened.cjs.map +1 -1
  21. package/dist/runtime-hardened.js +178 -79
  22. package/dist/runtime-hardened.js.map +1 -1
  23. package/dist/runtime.cjs +172 -77
  24. package/dist/runtime.cjs.map +1 -1
  25. package/dist/runtime.js +172 -77
  26. package/dist/runtime.js.map +1 -1
  27. package/dist/server.cjs +62 -9
  28. package/dist/server.cjs.map +1 -1
  29. package/dist/server.d.cts +29 -3
  30. package/dist/server.d.ts +29 -3
  31. package/dist/server.js +62 -10
  32. package/dist/server.js.map +1 -1
  33. package/dist/ssr/index.cjs +22 -4
  34. package/dist/ssr/index.cjs.map +1 -1
  35. package/dist/ssr/index.d.cts +7 -0
  36. package/dist/ssr/index.d.ts +7 -0
  37. package/dist/ssr/index.js +22 -4
  38. package/dist/ssr/index.js.map +1 -1
  39. package/package.json +1 -1
  40. package/dist/chunk-E3FV2VSU.cjs.map +0 -1
  41. package/dist/chunk-YRNYOZF3.js.map +0 -1
package/dist/index.d.cts CHANGED
@@ -334,6 +334,19 @@ declare function onError(handler: ErrorHandler): () => void;
334
334
  declare const Fragment: (props: {
335
335
  children?: unknown;
336
336
  }) => DocumentFragment;
337
+ /**
338
+ * Run `build()` with the SVG namespace active so nested `h()` calls create
339
+ * SVG-namespaced elements — including dual-use tags like `<a>` that `h()` would
340
+ * otherwise create as HTML. `h()` resolves tags by this explicit context (there
341
+ * is no automatic parent-walk); a `foreignObject` creates the SVG element but
342
+ * does not auto-switch its descendants back to HTML (author those with plain
343
+ * `h()` outside `svg()`). MathML is not supported.
344
+ *
345
+ * ```ts
346
+ * const icon = svg(() => h('svg', { viewBox: '0 0 10 10' }, h('a', { href: '#' })));
347
+ * ```
348
+ */
349
+ declare function svg<T extends Node>(build: () => T): T;
337
350
  /**
338
351
  * Remove all event listeners previously attached via `h()` on the given element.
339
352
  *
@@ -1175,4 +1188,4 @@ declare function onIntersect(el: HTMLElement, handler: (entry: IntersectionObser
1175
1188
  */
1176
1189
  declare function onMutation(el: HTMLElement, handler: (mutations: MutationRecord[]) => void, options?: MutationObserverInit): () => void;
1177
1190
 
1178
- export { $, $$, type CleanupFn, type ComponentDef, type Context, type CreateListOptions, type Dispatch, type ErrorHandler, type EventBus, Fragment, type HistoryControls, type IslandHydrateFn, type KeyOptions, type ListTransitionHooks, type PersistErrorPhase, type PersistOptions, type ReconcileResult, type Ref, type SetupFn, SignalGetter, type StoreSetter, type SwitchCase, activateIslands, addClass, batch, children, cleanup, closest, createBus, createComputed, createContext, createEffect, createErrorBoundary, createHistory, createList, createMemo, createPortal, createReducer, createRef, createRoot, createShow, createStore, createSuspense, createSwitch, createText, createUnownedRoot, deactivateAllIslands, deactivateIsland, defineComponent, delegate, disposeComponent, fragment, h, hydrateIsland, inject, mount, nextSibling, on, onCleanup, onError, onIntersect, onKey, onMount, onMutation, onResize, onUnmount, parent, persist, prevSibling, provide, reconcileList, removeClass, setAttr, setHTMLUnsafe, setStyle, setText, siblings, template, templateMany, toggleClass, trackDisposer, unprovide, untrack };
1191
+ export { $, $$, type CleanupFn, type ComponentDef, type Context, type CreateListOptions, type Dispatch, type ErrorHandler, type EventBus, Fragment, type HistoryControls, type IslandHydrateFn, type KeyOptions, type ListTransitionHooks, type PersistErrorPhase, type PersistOptions, type ReconcileResult, type Ref, type SetupFn, SignalGetter, type StoreSetter, type SwitchCase, activateIslands, addClass, batch, children, cleanup, closest, createBus, createComputed, createContext, createEffect, createErrorBoundary, createHistory, createList, createMemo, createPortal, createReducer, createRef, createRoot, createShow, createStore, createSuspense, createSwitch, createText, createUnownedRoot, deactivateAllIslands, deactivateIsland, defineComponent, delegate, disposeComponent, fragment, h, hydrateIsland, inject, mount, nextSibling, on, onCleanup, onError, onIntersect, onKey, onMount, onMutation, onResize, onUnmount, parent, persist, prevSibling, provide, reconcileList, removeClass, setAttr, setHTMLUnsafe, setStyle, setText, siblings, svg, template, templateMany, toggleClass, trackDisposer, unprovide, untrack };
package/dist/index.d.ts CHANGED
@@ -334,6 +334,19 @@ declare function onError(handler: ErrorHandler): () => void;
334
334
  declare const Fragment: (props: {
335
335
  children?: unknown;
336
336
  }) => DocumentFragment;
337
+ /**
338
+ * Run `build()` with the SVG namespace active so nested `h()` calls create
339
+ * SVG-namespaced elements — including dual-use tags like `<a>` that `h()` would
340
+ * otherwise create as HTML. `h()` resolves tags by this explicit context (there
341
+ * is no automatic parent-walk); a `foreignObject` creates the SVG element but
342
+ * does not auto-switch its descendants back to HTML (author those with plain
343
+ * `h()` outside `svg()`). MathML is not supported.
344
+ *
345
+ * ```ts
346
+ * const icon = svg(() => h('svg', { viewBox: '0 0 10 10' }, h('a', { href: '#' })));
347
+ * ```
348
+ */
349
+ declare function svg<T extends Node>(build: () => T): T;
337
350
  /**
338
351
  * Remove all event listeners previously attached via `h()` on the given element.
339
352
  *
@@ -1175,4 +1188,4 @@ declare function onIntersect(el: HTMLElement, handler: (entry: IntersectionObser
1175
1188
  */
1176
1189
  declare function onMutation(el: HTMLElement, handler: (mutations: MutationRecord[]) => void, options?: MutationObserverInit): () => void;
1177
1190
 
1178
- export { $, $$, type CleanupFn, type ComponentDef, type Context, type CreateListOptions, type Dispatch, type ErrorHandler, type EventBus, Fragment, type HistoryControls, type IslandHydrateFn, type KeyOptions, type ListTransitionHooks, type PersistErrorPhase, type PersistOptions, type ReconcileResult, type Ref, type SetupFn, SignalGetter, type StoreSetter, type SwitchCase, activateIslands, addClass, batch, children, cleanup, closest, createBus, createComputed, createContext, createEffect, createErrorBoundary, createHistory, createList, createMemo, createPortal, createReducer, createRef, createRoot, createShow, createStore, createSuspense, createSwitch, createText, createUnownedRoot, deactivateAllIslands, deactivateIsland, defineComponent, delegate, disposeComponent, fragment, h, hydrateIsland, inject, mount, nextSibling, on, onCleanup, onError, onIntersect, onKey, onMount, onMutation, onResize, onUnmount, parent, persist, prevSibling, provide, reconcileList, removeClass, setAttr, setHTMLUnsafe, setStyle, setText, siblings, template, templateMany, toggleClass, trackDisposer, unprovide, untrack };
1191
+ export { $, $$, type CleanupFn, type ComponentDef, type Context, type CreateListOptions, type Dispatch, type ErrorHandler, type EventBus, Fragment, type HistoryControls, type IslandHydrateFn, type KeyOptions, type ListTransitionHooks, type PersistErrorPhase, type PersistOptions, type ReconcileResult, type Ref, type SetupFn, SignalGetter, type StoreSetter, type SwitchCase, activateIslands, addClass, batch, children, cleanup, closest, createBus, createComputed, createContext, createEffect, createErrorBoundary, createHistory, createList, createMemo, createPortal, createReducer, createRef, createRoot, createShow, createStore, createSuspense, createSwitch, createText, createUnownedRoot, deactivateAllIslands, deactivateIsland, defineComponent, delegate, disposeComponent, fragment, h, hydrateIsland, inject, mount, nextSibling, on, onCleanup, onError, onIntersect, onKey, onMount, onMutation, onResize, onUnmount, parent, persist, prevSibling, provide, reconcileList, removeClass, setAttr, setHTMLUnsafe, setStyle, setText, siblings, svg, template, templateMany, toggleClass, trackDisposer, unprovide, untrack };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { hydrateIsland } from './chunk-YRNYOZF3.js';
2
- export { Fragment, cleanup, createList, createShow, fragment, h, hydrateIsland, reconcileList } from './chunk-YRNYOZF3.js';
1
+ import { hydrateIsland } from './chunk-AJP4OVCN.js';
2
+ export { Fragment, cleanup, createList, createShow, fragment, h, hydrateIsland, reconcileList, svg } from './chunk-AJP4OVCN.js';
3
3
  import { internalEffect, createUnownedRoot, createRoot, untrack, registerDisposer, createEffect, pushSuspenseContext, popSuspenseContext, batch } from './chunk-Y3A2EVVS.js';
4
4
  export { batch, createEffect, createMemo, createReducer, createRef, createResource, createRoot, createUnownedRoot, getBatchDepth, isComputed, isEffect, isEffectScope, isSignal, on, onCleanup, trigger, untrack } from './chunk-Y3A2EVVS.js';
5
5
  import { createSignal, __DEV__, reportError, value } from './chunk-ETPJTPYD.js';
@@ -216,8 +216,14 @@ function createSuspense(fallback, children2) {
216
216
  const isPending = pending() > 0;
217
217
  const newNode = isPending ? fallbackNode ??= fallback() : resolvedNode;
218
218
  if (newNode === currentNode) return;
219
- if (currentNode && currentNode.parentNode === parent2) {
220
- parent2.removeChild(currentNode);
219
+ if (currentNode) {
220
+ if (currentNode.parentNode === parent2) {
221
+ parent2.removeChild(currentNode);
222
+ } else if (currentNode.nodeType === 11) {
223
+ while (startMarker.nextSibling && startMarker.nextSibling !== endMarker) {
224
+ currentNode.appendChild(startMarker.nextSibling);
225
+ }
226
+ }
221
227
  }
222
228
  if (newNode) {
223
229
  parent2.insertBefore(newNode, endMarker);
@@ -273,6 +279,10 @@ function activateIslands(registry) {
273
279
  const sharedProps = scriptBlock ? JSON.parse(scriptBlock.textContent) : null;
274
280
  const islands = document.querySelectorAll("[data-forma-island]");
275
281
  for (const root of islands) {
282
+ const status = root.getAttribute("data-forma-status");
283
+ if (status === "active" || status === "hydrating" || status === "disposed" || status === "error") continue;
284
+ if (root.__formaScheduled) continue;
285
+ delete root.__formaDisposed;
276
286
  const id = parseInt(root.getAttribute("data-forma-island"), 10);
277
287
  const componentName = root.getAttribute("data-forma-component");
278
288
  const hydrateFn = registry[componentName];
@@ -283,30 +293,39 @@ function activateIslands(registry) {
283
293
  }
284
294
  const trigger2 = root.getAttribute("data-forma-hydrate") || "load";
285
295
  if (trigger2 === "visible") {
296
+ root.__formaScheduled = true;
286
297
  const observer = new IntersectionObserver(
287
298
  (entries) => {
288
299
  for (const entry of entries) {
289
300
  if (!entry.isIntersecting) continue;
290
301
  observer.disconnect();
302
+ delete root.__formaObserver;
291
303
  hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps);
292
304
  }
293
305
  },
294
306
  { rootMargin: "200px" }
295
307
  );
308
+ root.__formaObserver = observer;
296
309
  observer.observe(root);
297
310
  } else if (trigger2 === "idle") {
311
+ root.__formaScheduled = true;
298
312
  const hydrate = () => hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps);
299
313
  if (typeof requestIdleCallback === "function") {
300
- requestIdleCallback(hydrate);
314
+ const handle = requestIdleCallback(hydrate);
315
+ root.__formaIdleCancel = () => cancelIdleCallback(handle);
301
316
  } else {
302
- setTimeout(hydrate, 200);
317
+ const handle = setTimeout(hydrate, 200);
318
+ root.__formaIdleCancel = () => clearTimeout(handle);
303
319
  }
304
320
  } else if (trigger2 === "interaction") {
321
+ root.__formaScheduled = true;
305
322
  const hydrate = () => {
306
323
  root.removeEventListener("pointerdown", hydrate, true);
307
324
  root.removeEventListener("focusin", hydrate, true);
325
+ delete root.__formaInteractionHandler;
308
326
  hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps);
309
327
  };
328
+ root.__formaInteractionHandler = hydrate;
310
329
  root.addEventListener("pointerdown", hydrate, { capture: true, once: true });
311
330
  root.addEventListener("focusin", hydrate, { capture: true, once: true });
312
331
  } else {
@@ -315,6 +334,24 @@ function activateIslands(registry) {
315
334
  }
316
335
  }
317
336
  function deactivateIsland(el) {
337
+ const observer = el.__formaObserver;
338
+ if (observer) {
339
+ observer.disconnect();
340
+ delete el.__formaObserver;
341
+ }
342
+ const interactionHandler = el.__formaInteractionHandler;
343
+ if (interactionHandler) {
344
+ el.removeEventListener("pointerdown", interactionHandler, true);
345
+ el.removeEventListener("focusin", interactionHandler, true);
346
+ delete el.__formaInteractionHandler;
347
+ }
348
+ const idleCancel = el.__formaIdleCancel;
349
+ if (idleCancel) {
350
+ idleCancel();
351
+ delete el.__formaIdleCancel;
352
+ }
353
+ delete el.__formaScheduled;
354
+ el.__formaDisposed = true;
318
355
  const dispose = el.__formaDispose;
319
356
  if (typeof dispose === "function") {
320
357
  dispose();
@@ -323,13 +360,15 @@ function deactivateIsland(el) {
323
360
  }
324
361
  }
325
362
  function deactivateAllIslands(root = document) {
326
- const islands = root.querySelectorAll('[data-forma-status="active"]');
363
+ const islands = root.querySelectorAll("[data-forma-island]");
327
364
  for (const island of islands) {
328
365
  deactivateIsland(island);
329
366
  }
330
367
  }
331
368
  function hydrateIslandRoot(root, id, componentName, hydrateFn, sharedProps) {
369
+ if (root.__formaDisposed) return;
332
370
  try {
371
+ delete root.__formaScheduled;
333
372
  const props = loadIslandProps(root, id, sharedProps);
334
373
  root.setAttribute("data-forma-status", "hydrating");
335
374
  let activeRoot = root;