@askrjs/askr 0.0.69 → 0.0.71

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 (64) hide show
  1. package/capabilities.json +66 -0
  2. package/dist/actions/index.d.ts +1 -1
  3. package/dist/actions/index.js +9 -2
  4. package/dist/activity-C2tPn9Fr.js +152 -0
  5. package/dist/activity-DZ-NCYr8.d.ts +10 -0
  6. package/dist/{authoring-uaJ556aG.js → authoring-CXmUcaCe.js} +2 -2
  7. package/dist/benchmark.d.ts +1 -1
  8. package/dist/benchmark.js +6 -6
  9. package/dist/boot/index.d.ts +2 -2
  10. package/dist/boot/index.js +1 -1
  11. package/dist/{boot-aTei9rjA.js → boot-DIKbEA4Y.js} +11 -10
  12. package/dist/{cleanup-UyStxIHG.js → cleanup-D8Ufd9Ix.js} +29 -8
  13. package/dist/components/index.d.ts +1 -0
  14. package/dist/components/index.js +1 -0
  15. package/dist/control/index.d.ts +1 -1
  16. package/dist/control/index.js +1 -1
  17. package/dist/{control-CA45Yvvu.js → control-DVRBkN2X.js} +7 -2
  18. package/dist/{csp-nonce-HGZ0vbqT.js → csp-nonce-CwSRP3Jl.js} +16 -1
  19. package/dist/css-BuPaTOfe.js +70 -0
  20. package/dist/data/index.js +3 -3
  21. package/dist/{data-DHt_zO1G.js → data-DFcSmGvN.js} +2 -2
  22. package/dist/{data-runtime-SJ1BSUvk.js → data-runtime-rpV6-3XW.js} +13 -2
  23. package/dist/{deferred-zHtUheIQ.js → deferred-Cr58yIQD.js} +3 -4
  24. package/dist/foundations/index.d.ts +1 -1
  25. package/dist/foundations/index.js +1 -1
  26. package/dist/foundations/structures/index.d.ts +1 -1
  27. package/dist/foundations/structures/index.js +1 -1
  28. package/dist/{index-BFnTM1a8.d.ts → index-BOBtoY_r.d.ts} +34 -2
  29. package/dist/{index-DSClfSoC.d.ts → index-DxYJPVC4.d.ts} +1 -1
  30. package/dist/{index-Dh6ZF9yW.d.ts → index-UmwPZ8ZN.d.ts} +5 -0
  31. package/dist/{index-DjusBb1I.d.ts → index-u3KYoHlM.d.ts} +1 -1
  32. package/dist/index.d.ts +4 -5
  33. package/dist/index.js +12 -7
  34. package/dist/jsx-dev-runtime.d.ts +1 -0
  35. package/dist/jsx-runtime-C6Fs8Mmc.d.ts +2 -0
  36. package/dist/{jsx-runtime-aYZ8zb4q.d.ts → jsx-runtime-CL2r2HHQ.d.ts} +1 -0
  37. package/dist/jsx-runtime.d.ts +1 -1
  38. package/dist/{lifecycle-operations-SlPEK68H.js → lifecycle-operations-Db-_MG-O.js} +9 -12
  39. package/dist/{navigate-CV-RDqYP.d.ts → navigate-Cbq6QHVl.d.ts} +1 -1
  40. package/dist/{navigate-DpR-cML9.js → navigate-CuGQzS_Y.js} +8 -104
  41. package/dist/{portal-D7TC986A.js → portal-wY3j0vvp.js} +59 -1
  42. package/dist/{query-registry-CQIT4mXr.js → query-registry-Bu_cuMch.js} +1 -1
  43. package/dist/{renderer-CBBbYZUO.js → renderer-BJYY2Y8s.js} +91 -10
  44. package/dist/resources/index.d.ts +27 -8
  45. package/dist/resources/index.js +218 -4
  46. package/dist/{route-matching-DLBWDeXX.js → route-matching-M-f1VQRu.js} +276 -2
  47. package/dist/router/index.d.ts +7 -7
  48. package/dist/router/index.js +28 -17
  49. package/dist/{router-C0XQA62W.d.ts → router-C3vENhUh.d.ts} +1 -1
  50. package/dist/{selector-DueeR6Oz.js → selector-DEfqO1rA.js} +8 -0
  51. package/dist/ssg/index.d.ts +8 -1
  52. package/dist/ssg/index.js +53 -17
  53. package/dist/ssr/index.d.ts +15 -1
  54. package/dist/ssr/index.js +1 -1
  55. package/dist/{ssr-vE-KUgDV.js → ssr-BSUA9Y64.js} +72 -78
  56. package/dist/testing/index.d.ts +35 -2
  57. package/dist/testing/index.js +182 -3
  58. package/dist/{verify-hydration-ChyEiBAn.js → verify-hydration-CVSGv6Vs.js} +1 -1
  59. package/package.json +4 -2
  60. package/dist/attr-names-CjhzmHOn.js +0 -15
  61. package/dist/component-scope-CvPba6O6.d.ts +0 -12
  62. package/dist/invalidation-listeners-Des3AHYs.js +0 -13
  63. package/dist/jsx-runtime-X2SX2y8V.d.ts +0 -2
  64. package/dist/resource-operation-BJiLoLYZ.js +0 -276
package/dist/ssr/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import { u as SSRDataMissingError } from "../render-context-Clw3rFiO.js";
2
- import { a as renderResolvedToStringSync, c as createRenderContext, d as withRenderContextAsync, i as renderRouteRequestToString, l as getRenderContext, n as renderToString, o as renderToStringSync, r as renderRouteRequest, s as resolveRequest, t as renderToStream, u as withRenderContext } from "../ssr-vE-KUgDV.js";
2
+ import { a as renderResolvedToStringSync, c as createRenderContext, d as withRenderContextAsync, i as renderRouteRequestToString, l as getRenderContext, n as renderToString, o as renderToStringSync, r as renderRouteRequest, s as resolveRequest, t as renderToStream, u as withRenderContext } from "../ssr-BSUA9Y64.js";
3
3
  export { SSRDataMissingError, createRenderContext, getRenderContext, renderResolvedToStringSync, renderRouteRequest, renderRouteRequestToString, renderToStream, renderToString, renderToStringSync, resolveRequest, withRenderContext, withRenderContextAsync };
@@ -7,15 +7,15 @@ import { f as getCurrentComponentInstance, w as setCurrentComponentInstance } fr
7
7
  import { t as cleanupComponent } from "./component-cleanup-1ZFoLLHt.js";
8
8
  import { p as isPromiseLike } from "./lifecycle-batch-COgl8jMS.js";
9
9
  import { g as evaluateShowState, h as evaluateCaseState, i as evaluateForState, o as rollbackForStateTransaction, r as commitForStateTransaction } from "./for-internal-BtK9Htl0.js";
10
- import { _ as isPageRenderEnvelope, g as isEmptyPageRenderEnvelope, h as createPageRenderEnvelope, i as isDeferred, l as createRouteRegistry, m as resolveRouteRequest, t as DEFERRED_BOUNDARY } from "./deferred-zHtUheIQ.js";
10
+ import { _ as isPageRenderEnvelope, g as isEmptyPageRenderEnvelope, h as createPageRenderEnvelope, i as isDeferred, l as createRouteRegistry, m as resolveRouteRequest, t as DEFERRED_BOUNDARY } from "./deferred-Cr58yIQD.js";
11
11
  import { c as stopRenderPhase$1, o as startRenderPhase$1, t as configureRenderContextProvider, u as SSRDataMissingError } from "./render-context-Clw3rFiO.js";
12
- import { a as disposeDefaultPortalScope, t as DefaultPortal } from "./portal-D7TC986A.js";
13
- import { t as getPublicAttributeName } from "./attr-names-CjhzmHOn.js";
14
- import { r as validateCspNonce, t as CspNonceScope } from "./csp-nonce-HGZ0vbqT.js";
15
- import { t as createDataRuntime } from "./data-runtime-SJ1BSUvk.js";
16
- import { c as withTelemetry, i as dehydrateDataRuntime, t as createQueryPrefetchContext } from "./query-registry-CQIT4mXr.js";
17
- import { a as resolveRouteFromRoutes, t as _resolveRouteMatchFromRoutes } from "./route-matching-DLBWDeXX.js";
18
- import { a as route } from "./authoring-uaJ556aG.js";
12
+ import { a as resolveRouteFromRoutes, t as _resolveRouteMatchFromRoutes } from "./route-matching-M-f1VQRu.js";
13
+ import { a as disposeDefaultPortalScope, o as SSR_PORTAL_HOST, t as DefaultPortal } from "./portal-wY3j0vvp.js";
14
+ import { n as getPublicAttributeName, t as sanitizeCssValue } from "./css-BuPaTOfe.js";
15
+ import { a as isSafeHref, r as validateCspNonce, t as CspNonceScope } from "./csp-nonce-CwSRP3Jl.js";
16
+ import { t as createDataRuntime } from "./data-runtime-rpV6-3XW.js";
17
+ import { c as withTelemetry, i as dehydrateDataRuntime, t as createQueryPrefetchContext } from "./query-registry-Bu_cuMch.js";
18
+ import { a as route } from "./authoring-CXmUcaCe.js";
19
19
  import { n as renderDocument, t as SSR_RENDER_DATA_ATTR } from "./ssr-CbQO5xd3.js";
20
20
  //#region src/ssr/escape.ts
21
21
  /**
@@ -42,51 +42,6 @@ const VOID_ELEMENTS = /* @__PURE__ */ new Set([
42
42
  ]);
43
43
  const escapeCache = /* @__PURE__ */ new Map();
44
44
  const MAX_CACHE_SIZE = 256;
45
- const CSS_UNSAFE_RE = /[{}<>\\]/g;
46
- const CSS_URI_SCHEME_RE = /(?:^|[\s(,])([a-z][a-z0-9+.-]*):/i;
47
- const CSS_FUNCTION_NAME_RE = /([a-z-][a-z0-9-]*)\s*\(/gi;
48
- const CSS_ALLOWED_FUNCTIONS = /* @__PURE__ */ new Set([
49
- "var",
50
- "calc",
51
- "min",
52
- "max",
53
- "clamp",
54
- "rgb",
55
- "rgba",
56
- "hsl",
57
- "hsla",
58
- "lab",
59
- "lch",
60
- "oklab",
61
- "oklch",
62
- "color",
63
- "color-mix",
64
- "translate",
65
- "translatex",
66
- "translatey",
67
- "translatez",
68
- "scale",
69
- "scalex",
70
- "scaley",
71
- "scalez",
72
- "rotate",
73
- "rotatex",
74
- "rotatey",
75
- "rotatez",
76
- "skew",
77
- "skewx",
78
- "skewy",
79
- "matrix",
80
- "matrix3d",
81
- "linear-gradient",
82
- "radial-gradient",
83
- "conic-gradient",
84
- "repeating-linear-gradient",
85
- "repeating-radial-gradient",
86
- "repeating-conic-gradient",
87
- "cubic-bezier",
88
- "steps"
89
- ]);
90
45
  const STYLE_PROP_CACHE = /* @__PURE__ */ new Map();
91
46
  const MAX_STYLE_PROP_CACHE_SIZE = 512;
92
47
  function toKebabCached(prop) {
@@ -178,19 +133,7 @@ function escapeAttr(value) {
178
133
  return lastIndex === 0 ? value : escaped + value.slice(lastIndex);
179
134
  }
180
135
  /**
181
- * Escape CSS value to prevent injection attacks.
182
- * Removes characters that could break out of CSS context.
183
- */
184
- function escapeCssValue(value) {
185
- const str = String(value);
186
- if (CSS_URI_SCHEME_RE.test(str)) return "";
187
- if (str.includes("(")) {
188
- for (const match of str.matchAll(CSS_FUNCTION_NAME_RE)) if (!CSS_ALLOWED_FUNCTIONS.has(match[1].toLowerCase())) return "";
189
- }
190
- return str.replace(CSS_UNSAFE_RE, "");
191
- }
192
- /**
193
- * Convert style object to CSS string with value escaping
136
+ * Convert a style object to a CSS string, omitting unsafe values.
194
137
  * Optimized to avoid Object.entries allocation
195
138
  */
196
139
  function styleObjToCss(value) {
@@ -201,7 +144,7 @@ function styleObjToCss(value) {
201
144
  const v = styleObj[k];
202
145
  if (v === null || v === void 0 || v === false) continue;
203
146
  const prop = toKebabCached(k);
204
- const safeValue = escapeCssValue(String(v));
147
+ const safeValue = sanitizeCssValue(String(v));
205
148
  if (safeValue) result += `${prop}:${safeValue};`;
206
149
  }
207
150
  return result || null;
@@ -264,6 +207,10 @@ function createRenderContext(seed = 12345, opts = {}) {
264
207
  renderData: envelope,
265
208
  hydrationData: envelope,
266
209
  deferredBoundaries: [],
210
+ ssrPortals: {
211
+ slots: /* @__PURE__ */ new Map(),
212
+ nextHostId: 0
213
+ },
267
214
  cspNonce: opts.cspNonce
268
215
  };
269
216
  }
@@ -310,13 +257,7 @@ async function getAsyncRenderContextAccessor() {
310
257
  async function withRenderContextAsync(ctx, fn) {
311
258
  const accessor = await getAsyncRenderContextAccessor();
312
259
  if (accessor) return accessor.run(ctx, () => Promise.resolve(fn()));
313
- const previous = fallbackStack;
314
- fallbackStack = ctx;
315
- try {
316
- return await fn();
317
- } finally {
318
- fallbackStack = previous;
319
- }
260
+ throw new Error(FALLBACK_ASYNC_CONTEXT_ERROR);
320
261
  }
321
262
  /**
322
263
  * Get the current render context.
@@ -833,6 +774,7 @@ function renderAttrsDirect(props, sink) {
833
774
  }
834
775
  if (value === false || value === null || value === void 0) continue;
835
776
  const strValue = String(value);
777
+ if (attrName.toLowerCase() === "href" && !isSafeHref(strValue)) continue;
836
778
  sink.write(" ");
837
779
  sink.write(attrName);
838
780
  sink.write("=\"");
@@ -867,6 +809,7 @@ function renderAttrs(props, opts) {
867
809
  else if (value === false || value === null || value === void 0) continue;
868
810
  else {
869
811
  const strValue = String(value);
812
+ if (attrName.toLowerCase() === "href" && !isSafeHref(strValue)) continue;
870
813
  attrParts.push(` ${attrName}="${getEscapedAttrValue(strValue)}"`);
871
814
  }
872
815
  }
@@ -969,6 +912,47 @@ function renderRenderableSync(value, ctx) {
969
912
  if (value && typeof value === "object" && "type" in value) return renderNodeSync(value, ctx);
970
913
  return "";
971
914
  }
915
+ function resolveSSRPortals(html, ctx) {
916
+ let resolved = html;
917
+ const renderedHosts = /* @__PURE__ */ new Set();
918
+ for (;;) {
919
+ let foundHost = false;
920
+ for (const slot of ctx.ssrPortals.slots.values()) {
921
+ const explicitHosts = slot.hosts.filter((host) => !host.automatic);
922
+ const activeHosts = explicitHosts.length > 0 ? new Set(explicitHosts.map((host) => host.token)) : new Set(slot.hosts.map((host) => host.token));
923
+ for (const host of slot.hosts) {
924
+ if (renderedHosts.has(host.token)) continue;
925
+ foundHost = true;
926
+ const content = activeHosts.has(host.token) && slot.hasValue ? renderRenderableSync(slot.value, ctx) : "";
927
+ resolved = resolved.replace(host.token, () => content);
928
+ renderedHosts.add(host.token);
929
+ }
930
+ }
931
+ if (!foundHost) return resolved;
932
+ }
933
+ }
934
+ var SSRPortalSink = class {
935
+ constructor(sink) {
936
+ this.sink = sink;
937
+ this.bufferedChunks = null;
938
+ }
939
+ write(html) {
940
+ if (!html) return;
941
+ if (this.bufferedChunks) {
942
+ this.bufferedChunks.push(html);
943
+ return;
944
+ }
945
+ this.sink.write(html);
946
+ }
947
+ writePortalHost(token) {
948
+ this.bufferedChunks ??= [];
949
+ this.bufferedChunks.push(token);
950
+ }
951
+ flush(ctx) {
952
+ if (!this.bufferedChunks) return;
953
+ this.sink.write(resolveSSRPortals(this.bufferedChunks.join(""), ctx));
954
+ }
955
+ };
972
956
  function renderChildSync(child, ctx) {
973
957
  return renderRenderableSync(child, ctx);
974
958
  }
@@ -1037,6 +1021,7 @@ function renderNodeSync(node, ctx) {
1037
1021
  const { type, props } = node;
1038
1022
  if (typeof type === "function") return renderRenderableSync(inheritRenderableKey(node, executeComponentSync(type, props, ctx, getVNodeContextFrame(node) ?? null)), ctx);
1039
1023
  if (typeof type === "symbol") {
1024
+ if (type === SSR_PORTAL_HOST) return String(props?.token ?? "");
1040
1025
  if (type === Fragment) return renderChildrenSync(getRenderableChildren(node), ctx);
1041
1026
  if (type === __CONTROL_BOUNDARY__) return renderControlChildrenSync(node, ctx);
1042
1027
  if (type === DEFERRED_BOUNDARY) return renderDeferredBoundarySync(node, ctx);
@@ -1076,6 +1061,13 @@ function renderNodeSyncToSink(node, sink, ctx) {
1076
1061
  return;
1077
1062
  }
1078
1063
  if (typeof type === "symbol") {
1064
+ if (type === SSR_PORTAL_HOST) {
1065
+ const token = String(props?.token ?? "");
1066
+ const portalSink = sink;
1067
+ if (portalSink.writePortalHost) portalSink.writePortalHost(token);
1068
+ else sink.write(token);
1069
+ return;
1070
+ }
1079
1071
  if (type === Fragment) {
1080
1072
  renderChildrenSyncToSink(getRenderableChildren(node), sink, ctx);
1081
1073
  return;
@@ -1182,9 +1174,8 @@ function renderToStringSync(component, props, options) {
1182
1174
  if (!node) throw new Error("renderToStringSync: wrapped component returned empty");
1183
1175
  const sink = new StringSink();
1184
1176
  renderNodeSyncToSink(node, sink, ctx);
1185
- sink.write(serializeHydrationRenderData(ctx.hydrationData ?? void 0, ctx.dataRuntime));
1186
1177
  sink.end();
1187
- return sink.toString();
1178
+ return resolveSSRPortals(sink.toString(), ctx) + serializeHydrationRenderData(ctx.hydrationData ?? void 0, ctx.dataRuntime);
1188
1179
  } finally {
1189
1180
  try {
1190
1181
  stopRenderPhase();
@@ -1199,10 +1190,13 @@ function renderSSRRouteAppToSink(input) {
1199
1190
  withRenderContext(ctx, () => {
1200
1191
  startRenderPhase(ctx.renderData);
1201
1192
  try {
1202
- renderRenderableSyncToSink(executeComponentSync(ctx.cspNonce === void 0 ? route.handler : () => CspNonceScope({
1193
+ const app = executeComponentSync(ctx.cspNonce === void 0 ? route.handler : () => CspNonceScope({
1203
1194
  value: ctx.cspNonce,
1204
1195
  children: () => route.handler(params)
1205
- }), params, ctx), sink, ctx);
1196
+ }), params, ctx);
1197
+ const appSink = new SSRPortalSink(sink);
1198
+ renderRenderableSyncToSink(wrapWithDefaultPortal(app), appSink, ctx);
1199
+ appSink.flush(ctx);
1206
1200
  if (ctx.deferredBoundaries.length === 0) sink.write(serializeHydrationRenderData(ctx.hydrationData ?? data, ctx.dataRuntime));
1207
1201
  } finally {
1208
1202
  try {
@@ -1,5 +1,38 @@
1
+ import { s as ComponentFunction } from "../control-DO-iBEtV.js";
1
2
  import { C as Query, k as QueryStaleReason } from "../index-Bki2rqcr.js";
2
- import { N as RouteRegistry, x as RouteMatch } from "../router-C0XQA62W.js";
3
+ import { N as RouteRegistry, p as RouteAuthOptions, x as RouteMatch } from "../router-C3vENhUh.js";
4
+ //#region src/testing/render.d.ts
5
+ interface RenderOptions {
6
+ /**
7
+ * Existing element to own for the duration of the render. When omitted, the
8
+ * harness appends a managed `<div>` to `document.body`.
9
+ */
10
+ container?: HTMLElement;
11
+ /** Surface lifecycle cleanup errors during unmount. */
12
+ cleanupStrict?: boolean;
13
+ }
14
+ interface RouteRenderOptions extends RenderOptions {
15
+ registry: RouteRegistry;
16
+ /** Initial path, query, and hash for the routed render. */
17
+ url?: string;
18
+ auth?: RouteAuthOptions;
19
+ }
20
+ type DispatchEventInit = EventInit | UIEventInit | FocusEventInit | MouseEventInit | WheelEventInit | KeyboardEventInit | InputEventInit | CompositionEventInit | PointerEventInit | TouchEventInit | DragEventInit;
21
+ interface RenderResult {
22
+ readonly container: HTMLElement;
23
+ readonly root: HTMLElement;
24
+ flush(): void;
25
+ dispatch(target: EventTarget, event: Event | string, init?: DispatchEventInit): boolean;
26
+ unmount(): void;
27
+ cleanup(): void;
28
+ }
29
+ declare function flush(): void;
30
+ declare function dispatch(target: EventTarget, event: Event | string, init?: DispatchEventInit): boolean;
31
+ declare function cleanup(target: RenderResult | HTMLElement): void;
32
+ declare function render(component: ComponentFunction, options?: RenderOptions): RenderResult;
33
+ declare function mount(component: ComponentFunction, options?: RenderOptions): RenderResult;
34
+ declare function renderRoute(options: RouteRenderOptions): Promise<RenderResult>;
35
+ //#endregion
3
36
  //#region src/testing/index.d.ts
4
37
  type MockRefresh = () => void | Promise<void>;
5
38
  interface MockQueryOptions {
@@ -47,4 +80,4 @@ declare function createInvalidationRecorder(): InvalidationRecorder;
47
80
  declare function matchRoute(path: string, options: MatchRouteOptions): RouteMatch | null;
48
81
  declare function getRouteWarnings(options: MatchRouteOptions): RoutePatternWarning[];
49
82
  //#endregion
50
- export { InvalidationRecord, InvalidationRecorder, MockQueryOptions, MockRefresh, RoutePatternWarning, createInvalidationRecorder, getRouteWarnings, matchRoute, mockQuery, queryState };
83
+ export { InvalidationRecord, InvalidationRecorder, MockQueryOptions, MockRefresh, type RenderOptions, type RenderResult, RoutePatternWarning, type RouteRenderOptions, cleanup, createInvalidationRecorder, dispatch, flush, getRouteWarnings, matchRoute, mockQuery, mount, queryState, render, renderRoute };
@@ -1,5 +1,184 @@
1
- import { t as addInvalidationListener } from "../invalidation-listeners-Des3AHYs.js";
2
- import { r as computeRouteActivityMatches } from "../route-matching-DLBWDeXX.js";
1
+ import { r as flushRuntimeScheduler } from "../access-ePqdQqkV.js";
2
+ import { r as computeRouteActivityMatches } from "../route-matching-M-f1VQRu.js";
3
+ import { l as addInvalidationListener } from "../data-runtime-rpV6-3XW.js";
4
+ import { a as cleanupApp, r as createSPA, t as createIsland } from "../boot-DIKbEA4Y.js";
5
+ //#region src/testing/render.ts
6
+ const renderStates = /* @__PURE__ */ new WeakMap();
7
+ const eventConstructorNames = {
8
+ auxclick: ["MouseEvent"],
9
+ click: ["MouseEvent"],
10
+ contextmenu: ["MouseEvent"],
11
+ dblclick: ["MouseEvent"],
12
+ mousedown: ["MouseEvent"],
13
+ mouseenter: ["MouseEvent"],
14
+ mouseleave: ["MouseEvent"],
15
+ mousemove: ["MouseEvent"],
16
+ mouseout: ["MouseEvent"],
17
+ mouseover: ["MouseEvent"],
18
+ mouseup: ["MouseEvent"],
19
+ pointercancel: ["PointerEvent", "MouseEvent"],
20
+ pointerdown: ["PointerEvent", "MouseEvent"],
21
+ pointerenter: ["PointerEvent", "MouseEvent"],
22
+ pointerleave: ["PointerEvent", "MouseEvent"],
23
+ pointermove: ["PointerEvent", "MouseEvent"],
24
+ pointerout: ["PointerEvent", "MouseEvent"],
25
+ pointerover: ["PointerEvent", "MouseEvent"],
26
+ pointerup: ["PointerEvent", "MouseEvent"],
27
+ keydown: ["KeyboardEvent"],
28
+ keypress: ["KeyboardEvent"],
29
+ keyup: ["KeyboardEvent"],
30
+ blur: ["FocusEvent"],
31
+ focus: ["FocusEvent"],
32
+ focusin: ["FocusEvent"],
33
+ focusout: ["FocusEvent"],
34
+ beforeinput: ["InputEvent"],
35
+ input: ["InputEvent"],
36
+ compositionend: ["CompositionEvent"],
37
+ compositionstart: ["CompositionEvent"],
38
+ compositionupdate: ["CompositionEvent"],
39
+ drag: ["DragEvent", "MouseEvent"],
40
+ dragend: ["DragEvent", "MouseEvent"],
41
+ dragenter: ["DragEvent", "MouseEvent"],
42
+ dragleave: ["DragEvent", "MouseEvent"],
43
+ dragover: ["DragEvent", "MouseEvent"],
44
+ dragstart: ["DragEvent", "MouseEvent"],
45
+ drop: ["DragEvent", "MouseEvent"],
46
+ touchcancel: ["TouchEvent"],
47
+ touchend: ["TouchEvent"],
48
+ touchmove: ["TouchEvent"],
49
+ touchstart: ["TouchEvent"],
50
+ wheel: ["WheelEvent", "MouseEvent"]
51
+ };
52
+ function requireDocument() {
53
+ if (typeof document === "undefined" || typeof document.createElement !== "function" || !document.body) throw new Error("@askrjs/askr/testing render requires a DOM environment. Configure Vitest with environment: \"jsdom\".");
54
+ return document;
55
+ }
56
+ function requireWindow() {
57
+ if (typeof window === "undefined" || !window.location || !window.history || typeof window.history.replaceState !== "function") throw new Error("@askrjs/askr/testing renderRoute requires a browser-like DOM environment. Configure Vitest with environment: \"jsdom\".");
58
+ return window;
59
+ }
60
+ function prepareContainer(options) {
61
+ const currentDocument = requireDocument();
62
+ const managed = options?.container === void 0;
63
+ const providedContainer = options?.container;
64
+ if (providedContainer !== void 0 && (!providedContainer || providedContainer.nodeType !== 1 || typeof providedContainer.querySelector !== "function" || typeof providedContainer.replaceChildren !== "function")) throw new TypeError("@askrjs/askr/testing render options.container must be an HTMLElement.");
65
+ const container = providedContainer ?? currentDocument.createElement("div");
66
+ if (renderStates.get(container)?.active) throw new Error("@askrjs/askr/testing cannot render into a container that already has an active render.");
67
+ if (managed) {
68
+ container.setAttribute("data-askr-testing-root", "");
69
+ currentDocument.body.appendChild(container);
70
+ }
71
+ const state = {
72
+ active: true,
73
+ managed
74
+ };
75
+ renderStates.set(container, state);
76
+ return {
77
+ container,
78
+ state
79
+ };
80
+ }
81
+ function getBaseEventConstructor(target) {
82
+ if (typeof Element !== "undefined" && target instanceof Element) return target.ownerDocument.defaultView?.Event ?? Event;
83
+ return Event;
84
+ }
85
+ function getEventConstructor(target, type) {
86
+ const realm = (typeof Element !== "undefined" && target instanceof Element ? target.ownerDocument.defaultView : typeof window !== "undefined" ? window : void 0) ?? globalThis;
87
+ for (const name of eventConstructorNames[type] ?? []) {
88
+ const constructor = realm[name];
89
+ if (typeof constructor === "function") return constructor;
90
+ }
91
+ return getBaseEventConstructor(target);
92
+ }
93
+ function isEventForTarget(target, value) {
94
+ if (value instanceof getBaseEventConstructor(target)) return true;
95
+ return typeof Event !== "undefined" && value instanceof Event;
96
+ }
97
+ function flush() {
98
+ flushRuntimeScheduler();
99
+ }
100
+ function dispatch(target, event, init = {}) {
101
+ if (!target || typeof target.dispatchEvent !== "function") throw new TypeError("@askrjs/askr/testing dispatch requires an EventTarget.");
102
+ if (typeof event !== "string" && !isEventForTarget(target, event)) throw new TypeError("@askrjs/askr/testing dispatch requires an Event instance or event type string.");
103
+ const dispatchedEvent = typeof event === "string" ? new (getEventConstructor(target, event))(event, {
104
+ bubbles: true,
105
+ cancelable: true,
106
+ ...init
107
+ }) : event;
108
+ return target.dispatchEvent(dispatchedEvent);
109
+ }
110
+ function cleanupContainer(container) {
111
+ const state = renderStates.get(container);
112
+ if (!state?.active) return;
113
+ state.active = false;
114
+ try {
115
+ cleanupApp(container);
116
+ } finally {
117
+ container.replaceChildren();
118
+ if (state.managed) container.remove();
119
+ if (state.restoreHistory && state.restoreUrl) state.restoreHistory.replaceState({}, "", state.restoreUrl);
120
+ renderStates.delete(container);
121
+ }
122
+ }
123
+ function isRenderResult(target) {
124
+ return "container" in target && "cleanup" in target;
125
+ }
126
+ function cleanup(target) {
127
+ cleanupContainer(isRenderResult(target) ? target.container : target);
128
+ }
129
+ function createRenderResult(container) {
130
+ return {
131
+ container,
132
+ root: container,
133
+ flush,
134
+ dispatch,
135
+ unmount: () => cleanupContainer(container),
136
+ cleanup: () => cleanupContainer(container)
137
+ };
138
+ }
139
+ function render(component, options) {
140
+ if (typeof component !== "function") throw new TypeError("@askrjs/askr/testing render requires a component function.");
141
+ const { container } = prepareContainer(options);
142
+ try {
143
+ createIsland({
144
+ root: container,
145
+ component,
146
+ cleanupStrict: options?.cleanupStrict
147
+ });
148
+ flush();
149
+ return createRenderResult(container);
150
+ } catch (error) {
151
+ cleanupContainer(container);
152
+ throw error;
153
+ }
154
+ }
155
+ function mount(component, options) {
156
+ return render(component, options);
157
+ }
158
+ async function renderRoute(options) {
159
+ if (!options?.registry) throw new TypeError("@askrjs/askr/testing renderRoute requires a route registry.");
160
+ const currentWindow = requireWindow();
161
+ const { container, state } = prepareContainer(options);
162
+ try {
163
+ if (options.url !== void 0) {
164
+ state.restoreHistory = currentWindow.history;
165
+ state.restoreUrl = `${currentWindow.location.pathname}${currentWindow.location.search}${currentWindow.location.hash}`;
166
+ currentWindow.history.replaceState({}, "", options.url);
167
+ }
168
+ await createSPA({
169
+ root: container,
170
+ registry: options.registry,
171
+ auth: options.auth,
172
+ cleanupStrict: options.cleanupStrict
173
+ });
174
+ flush();
175
+ return createRenderResult(container);
176
+ } catch (error) {
177
+ cleanupContainer(container);
178
+ throw error;
179
+ }
180
+ }
181
+ //#endregion
3
182
  //#region src/testing/index.ts
4
183
  function normalizeRefresh(options) {
5
184
  return async () => {
@@ -163,4 +342,4 @@ function getRouteWarnings(options) {
163
342
  });
164
343
  }
165
344
  //#endregion
166
- export { createInvalidationRecorder, getRouteWarnings, matchRoute, mockQuery, queryState };
345
+ export { cleanup, createInvalidationRecorder, dispatch, flush, getRouteWarnings, matchRoute, mockQuery, mount, queryState, render, renderRoute };
@@ -1,5 +1,5 @@
1
1
  import { t as SSR_RENDER_DATA_ATTR } from "./ssr-CbQO5xd3.js";
2
- import { a as renderResolvedToStringSync } from "./ssr-vE-KUgDV.js";
2
+ import { a as renderResolvedToStringSync } from "./ssr-BSUA9Y64.js";
3
3
  //#region src/ssr/verify-hydration.ts
4
4
  function normalizeHydrationHtml(html) {
5
5
  const template = document.createElement("template");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askrjs/askr",
3
- "version": "0.0.69",
3
+ "version": "0.0.71",
4
4
  "description": "Actor-backed deterministic UI framework",
5
5
  "keywords": [
6
6
  "askr",
@@ -23,6 +23,7 @@
23
23
  "url": "git+https://github.com/askrjs/askr.git"
24
24
  },
25
25
  "files": [
26
+ "capabilities.json",
26
27
  "dist/**/*.js",
27
28
  "dist/**/*.d.ts"
28
29
  ],
@@ -113,7 +114,8 @@
113
114
  "types": "./dist/jsx-dev-runtime.d.ts",
114
115
  "import": "./dist/jsx-dev-runtime.js"
115
116
  },
116
- "./package.json": "./package.json"
117
+ "./package.json": "./package.json",
118
+ "./capabilities.json": "./capabilities.json"
117
119
  },
118
120
  "publishConfig": {
119
121
  "access": "public"
@@ -1,15 +0,0 @@
1
- //#region src/common/attr-names.ts
2
- const PUBLIC_ATTRIBUTE_NAME_MAP = {
3
- className: "class",
4
- htmlFor: "for",
5
- strokeWidth: "stroke-width",
6
- strokeLinecap: "stroke-linecap",
7
- strokeLinejoin: "stroke-linejoin",
8
- fillRule: "fill-rule",
9
- clipRule: "clip-rule"
10
- };
11
- function getPublicAttributeName(propName) {
12
- return PUBLIC_ATTRIBUTE_NAME_MAP[propName] ?? propName;
13
- }
14
- //#endregion
15
- export { getPublicAttributeName as t };
@@ -1,12 +0,0 @@
1
- //#region src/runtime/component-scope.d.ts
2
- /**
3
- * Get the abort signal for the current component.
4
- *
5
- * The signal is guaranteed to be aborted when:
6
- * - Component unmounts
7
- * - Navigation occurs (different route)
8
- * - Parent is destroyed
9
- */
10
- declare function getSignal(): AbortSignal;
11
- //#endregion
12
- export { getSignal as t };
@@ -1,13 +0,0 @@
1
- //#region src/data/invalidation-listeners.ts
2
- const invalidationListeners = /* @__PURE__ */ new Set();
3
- function addInvalidationListener(listener) {
4
- invalidationListeners.add(listener);
5
- return () => {
6
- invalidationListeners.delete(listener);
7
- };
8
- }
9
- function emitInvalidation(event) {
10
- for (const listener of invalidationListeners) listener(event);
11
- }
12
- //#endregion
13
- export { emitInvalidation as n, addInvalidationListener as t };
@@ -1,2 +0,0 @@
1
- import "./types-DEhT-Nrv.js";
2
- import "./jsx-runtime-aYZ8zb4q.js";