@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
@@ -0,0 +1,66 @@
1
+ {
2
+ "version": 1,
3
+ "package": "@askrjs/askr",
4
+ "capabilities": [
5
+ {
6
+ "intent": "reactive state and derived views",
7
+ "package": "@askrjs/askr",
8
+ "import": "@askrjs/askr",
9
+ "exports": ["state", "derive", "selector", "For"],
10
+ "constraints": ["component render scope", "stable call order"],
11
+ "stability": "stable",
12
+ "docs": "https://github.com/askrjs/askr/blob/main/docs/guides/state.md",
13
+ "docsPath": "docs/guides/state.md"
14
+ },
15
+ {
16
+ "intent": "routing and navigation",
17
+ "package": "@askrjs/askr",
18
+ "import": "@askrjs/askr/router",
19
+ "exports": ["route", "Link", "navigate", "createRouteRegistry"],
20
+ "constraints": ["route registry owns navigation"],
21
+ "stability": "stable",
22
+ "docs": "https://github.com/askrjs/askr/blob/main/docs/guides/router.md",
23
+ "docsPath": "docs/guides/router.md"
24
+ },
25
+ {
26
+ "intent": "server rendering",
27
+ "package": "@askrjs/askr",
28
+ "import": "@askrjs/askr/ssr",
29
+ "exports": ["renderToString"],
30
+ "constraints": ["browser globals require lazy client targets"],
31
+ "stability": "stable",
32
+ "docs": "https://github.com/askrjs/askr/blob/main/docs/guides/ssr.md",
33
+ "docsPath": "docs/guides/ssr.md"
34
+ },
35
+ {
36
+ "intent": "static generation",
37
+ "package": "@askrjs/askr",
38
+ "import": "@askrjs/askr/ssg",
39
+ "exports": ["createStaticGen"],
40
+ "constraints": ["routes must be deterministic"],
41
+ "stability": "stable",
42
+ "docs": "https://github.com/askrjs/askr/blob/main/docs/guides/ssg.md",
43
+ "docsPath": "docs/guides/ssg.md"
44
+ },
45
+ {
46
+ "intent": "error boundaries",
47
+ "package": "@askrjs/askr",
48
+ "import": "@askrjs/askr/components",
49
+ "exports": ["ErrorBoundary"],
50
+ "constraints": ["portal hosts are finalized during render"],
51
+ "stability": "stable",
52
+ "docs": "https://github.com/askrjs/askr/blob/main/docs/reference/api.md",
53
+ "docsPath": "docs/reference/api.md"
54
+ },
55
+ {
56
+ "intent": "portals",
57
+ "package": "@askrjs/askr",
58
+ "import": "@askrjs/askr/foundations/structures",
59
+ "exports": ["Portal", "DefaultPortal"],
60
+ "constraints": ["portal hosts are finalized during render"],
61
+ "stability": "stable",
62
+ "docs": "https://github.com/askrjs/askr/blob/main/docs/reference/api.md",
63
+ "docsPath": "docs/reference/api.md"
64
+ }
65
+ ]
66
+ }
@@ -1,2 +1,2 @@
1
- import { a as action, i as ActionValidationError, n as ActionForm, o as defineAction, r as ActionStatus, t as ActionDescriptor } from "../index-DSClfSoC.js";
1
+ import { a as action, i as ActionValidationError, n as ActionForm, o as defineAction, r as ActionStatus, t as ActionDescriptor } from "../index-DxYJPVC4.js";
2
2
  export { ActionDescriptor, ActionForm, ActionStatus, ActionValidationError, action, defineAction };
@@ -2,7 +2,7 @@ import { d as getCurrentAppRenderRuntime } from "../component-scope-CC3cojX9.js"
2
2
  import { r as getCurrentRenderData } from "../render-context-Clw3rFiO.js";
3
3
  import { t as state } from "../state-CVuQVjvK.js";
4
4
  import { jsx, jsxs } from "../jsx-runtime.js";
5
- import { c as resolveDataRuntimeState, s as invalidateQueriesForRuntime } from "../data-runtime-SJ1BSUvk.js";
5
+ import { c as resolveDataRuntimeState, s as invalidateQueriesForRuntime } from "../data-runtime-rpV6-3XW.js";
6
6
  //#region src/actions/runtime.ts
7
7
  const emptyFramework = Object.freeze({});
8
8
  /** @internal Read Askr-owned state from the current application root. */
@@ -59,6 +59,12 @@ function initialStatus(actionId) {
59
59
  error: replay
60
60
  } : { pending: false };
61
61
  }
62
+ function normalizeActionRedirect(value) {
63
+ const current = new URL(location.href);
64
+ const target = new URL(value, current);
65
+ if (target.protocol !== "http:" && target.protocol !== "https:" || target.origin !== current.origin) throw new TypeError("Action redirects must stay on the current origin.");
66
+ return `${target.pathname}${target.search}${target.hash}`;
67
+ }
62
68
  /** Returns a command handle, rather than a hook. */
63
69
  function action(descriptor) {
64
70
  const token = csrfToken();
@@ -82,13 +88,14 @@ function action(descriptor) {
82
88
  });
83
89
  const envelope = await response.json();
84
90
  if (!response.ok) throw envelope.error ?? validationError(envelope, descriptor.id) ?? /* @__PURE__ */ new Error(`Action failed (${response.status}).`);
91
+ const redirect = typeof envelope.redirect === "string" ? normalizeActionRedirect(envelope.redirect) : void 0;
85
92
  const invalidates = Array.isArray(envelope.invalidates) ? envelope.invalidates.filter((prefix) => typeof prefix === "string") : descriptor.invalidates;
86
93
  for (const prefix of invalidates) invalidateQueriesForRuntime(runtime, prefix, true);
87
94
  setValue({
88
95
  pending: false,
89
96
  result: envelope.result
90
97
  });
91
- if (typeof envelope.redirect === "string") location.assign(envelope.redirect);
98
+ if (redirect) location.assign(redirect);
92
99
  return envelope.result;
93
100
  } catch (error) {
94
101
  setValue({
@@ -0,0 +1,152 @@
1
+ import { a as registerCommitOperation } from "./component-internal-CPjM4n8M.js";
2
+ import { l as notifyReadableReaders, o as markReactivePropsDirtySource, s as markReadableDerivedSubscribersDirty, u as recordReadableRead } from "./readable-BYSoWJSv.js";
3
+ import { d as getCurrentAppRenderRuntime, f as getCurrentComponentInstance, i as claimHookIndex } from "./component-scope-CC3cojX9.js";
4
+ import { n as getActiveRenderContext } from "./render-context-Clw3rFiO.js";
5
+ import { c as deepFreeze, g as getActiveRoutes, l as makeQuery, n as computeMatchesFromRoutes, u as parseLocation } from "./route-matching-M-f1VQRu.js";
6
+ import { n as syncRouteActivitySnapshot } from "./route-activity-CNJfpwx-.js";
7
+ //#region src/common/app-render-runtime.ts
8
+ const stagedRouteLocations = /* @__PURE__ */ new WeakMap();
9
+ function createAppRenderRuntime(input = {}) {
10
+ return {
11
+ framework: Object.freeze({ ...input.framework }),
12
+ route: input.route,
13
+ hasRoute: input.hasRoute ?? false
14
+ };
15
+ }
16
+ function stageAppRenderRouteLocation(runtime, href) {
17
+ stagedRouteLocations.set(runtime, href);
18
+ }
19
+ function getStagedAppRenderRouteLocation(runtime) {
20
+ return runtime ? stagedRouteLocations.get(runtime) : void 0;
21
+ }
22
+ function clearStagedAppRenderRouteLocation(runtime) {
23
+ if (runtime) stagedRouteLocations.delete(runtime);
24
+ }
25
+ //#endregion
26
+ //#region src/router/activity.ts
27
+ function routeSignature(route) {
28
+ return `${route.path}\u0000${JSON.stringify(route.query.toJSON())}\u0000${route.hash ?? ""}`;
29
+ }
30
+ let currentRouteSnapshot = buildRouteSnapshot("/", "", "");
31
+ const currentRouteSource = (() => currentRouteSnapshot);
32
+ currentRouteSource._readers = /* @__PURE__ */ new Map();
33
+ function onRouteChange(fn, options = {}) {
34
+ const instance = getCurrentComponentInstance();
35
+ if (!instance) return;
36
+ const route = currentRoute();
37
+ const index = claimHookIndex(instance, "route-change");
38
+ const slots = instance.lifecycleSlots ??= [];
39
+ const existing = slots[index];
40
+ if (existing && existing.kind !== "route-change") throw new Error(`onRouteChange() lifecycle order violation: slot ${index} already belongs to ${existing.kind}(). Keep lifecycle primitives in a stable top-level order.`);
41
+ const slot = existing ?? {
42
+ kind: "route-change",
43
+ previous: null,
44
+ pending: null,
45
+ cleanup: null,
46
+ cleanupRegistered: false,
47
+ callback: fn,
48
+ immediate: options.immediate === true
49
+ };
50
+ slots[index] = slot;
51
+ slot.pending = route;
52
+ slot.callback = fn;
53
+ slot.immediate = options.immediate === true;
54
+ if (!slot.cleanupRegistered) {
55
+ instance.cleanupFns ??= [];
56
+ instance.cleanupFns.push(() => {
57
+ slot.cleanup?.();
58
+ slot.cleanup = null;
59
+ });
60
+ slot.cleanupRegistered = true;
61
+ }
62
+ if (!slot.previous) {
63
+ registerCommitOperation(() => {
64
+ const committed = slot.pending;
65
+ if (!committed) return;
66
+ if (slot.immediate) slot.cleanup = slot.callback(committed, null) ?? null;
67
+ slot.previous = committed;
68
+ });
69
+ return;
70
+ }
71
+ if (routeSignature(slot.previous) === routeSignature(route)) return;
72
+ registerCommitOperation(() => {
73
+ const previous = slot.previous;
74
+ const committed = slot.pending;
75
+ if (!previous || !committed || routeSignature(previous) === routeSignature(committed)) return;
76
+ slot.cleanup?.();
77
+ slot.cleanup = slot.callback(committed, previous) ?? null;
78
+ slot.previous = committed;
79
+ });
80
+ }
81
+ let serverLocation = null;
82
+ function setServerLocation(url) {
83
+ serverLocation = url;
84
+ if (url) {
85
+ const parsed = parseLocation(url);
86
+ syncRouteActivitySnapshot(parsed.pathname, computeMatchesFromRoutes(parsed.pathname, getActiveRoutes()));
87
+ return;
88
+ }
89
+ syncRouteActivitySnapshot(currentRouteSnapshot.path, currentRouteSnapshot.matches);
90
+ }
91
+ function buildRouteSnapshot(pathname, search, hash) {
92
+ const query = makeQuery(search);
93
+ const matches = computeMatchesFromRoutes(pathname, getActiveRoutes());
94
+ return Object.freeze({
95
+ path: pathname,
96
+ params: deepFreeze({ ...matches[0]?.params }),
97
+ query,
98
+ hash: hash || null,
99
+ matches: Object.freeze(matches)
100
+ });
101
+ }
102
+ function setCurrentRouteSnapshot(pathname, search, hash, activityMatches) {
103
+ currentRouteSnapshot = buildRouteSnapshot(pathname, search, hash);
104
+ syncRouteActivitySnapshot(pathname, activityMatches ?? currentRouteSnapshot.matches);
105
+ const instance = getCurrentComponentInstance();
106
+ markReadableDerivedSubscribersDirty(currentRouteSource);
107
+ markReactivePropsDirtySource(currentRouteSource);
108
+ notifyReadableReaders(currentRouteSource, instance);
109
+ }
110
+ function readCurrentRouteLocation() {
111
+ const renderContext = getActiveRenderContext();
112
+ if (renderContext?.url) return parseLocation(renderContext.url);
113
+ const stagedRouteLocation = getStagedAppRenderRouteLocation(getCurrentAppRenderRuntime());
114
+ if (stagedRouteLocation) return parseLocation(stagedRouteLocation);
115
+ if (typeof window !== "undefined" && window.location) return {
116
+ pathname: window.location.pathname || "/",
117
+ search: window.location.search || "",
118
+ hash: window.location.hash || ""
119
+ };
120
+ if (serverLocation) return parseLocation(serverLocation);
121
+ return {
122
+ pathname: currentRouteSnapshot.path,
123
+ search: "",
124
+ hash: currentRouteSnapshot.hash ?? ""
125
+ };
126
+ }
127
+ function readCurrentRouteSnapshot() {
128
+ if (!getCurrentComponentInstance()) throw new Error("currentRoute() can only be called during component render execution. Call currentRoute() from inside your component function.");
129
+ const { pathname, search, hash } = readCurrentRouteLocation();
130
+ const query = makeQuery(search);
131
+ const matches = computeMatchesFromRoutes(pathname, getActiveRoutes());
132
+ const params = deepFreeze({ ...getActiveRenderContext()?.params ?? matches[0]?.params ?? {} });
133
+ return Object.freeze({
134
+ path: pathname,
135
+ params,
136
+ query,
137
+ hash: hash || null,
138
+ matches: Object.freeze(matches)
139
+ });
140
+ }
141
+ function currentRoute() {
142
+ const instance = getCurrentComponentInstance();
143
+ if (!instance) throw new Error("currentRoute() can only be called during component render execution. Call currentRoute() from inside your component function.");
144
+ if (typeof window === "undefined" || instance.ssr) return readCurrentRouteSnapshot();
145
+ recordReadableRead(currentRouteSource);
146
+ return readCurrentRouteSnapshot();
147
+ }
148
+ function syncCurrentRouteSnapshot(pathname, search, hash, activityMatches) {
149
+ setCurrentRouteSnapshot(pathname, search, hash, activityMatches);
150
+ }
151
+ //#endregion
152
+ export { clearStagedAppRenderRouteLocation as a, syncCurrentRouteSnapshot as i, onRouteChange as n, createAppRenderRuntime as o, setServerLocation as r, stageAppRenderRouteLocation as s, currentRoute as t };
@@ -0,0 +1,10 @@
1
+ import { B as RouteSnapshot, E as RouteParams } from "./router-C3vENhUh.js";
2
+ //#region src/router/activity.d.ts
3
+ interface RouteChangeOptions {
4
+ immediate?: boolean;
5
+ }
6
+ type RouteChangeCleanup = void | (() => void);
7
+ declare function onRouteChange(fn: (current: RouteSnapshot, previous: RouteSnapshot | null) => RouteChangeCleanup, options?: RouteChangeOptions): void;
8
+ declare function currentRoute<TParams extends RouteParams = RouteParams>(): RouteSnapshot<TParams>;
9
+ //#endregion
10
+ export { onRouteChange as i, RouteChangeOptions as n, currentRoute as r, RouteChangeCleanup as t };
@@ -1,6 +1,6 @@
1
1
  import { f as getCurrentComponentInstance } from "./component-scope-CC3cojX9.js";
2
- import { T as getExecutionModel, x as createRouteHandler } from "./deferred-zHtUheIQ.js";
3
- import { A as insertRecordSorted, C as getCurrentPathPrefix, I as computeRank, L as normalizeRouteSegmentName, M as pushRegistrationScope, O as hasActivePageScope, R as parseSegments, S as getCurrentPageScope, _ as getCurrentInheritedAuthRequirements, b as getCurrentLayoutChain, f as addRouteToStores, p as assertRouteRegistrationUnlocked, v as getCurrentInheritedMeta, w as getCurrentScopeKind, x as getCurrentPageChain, y as getCurrentInheritedPolicies } from "./route-matching-DLBWDeXX.js";
2
+ import { T as getExecutionModel, x as createRouteHandler } from "./deferred-Cr58yIQD.js";
3
+ import { A as insertRecordSorted, C as getCurrentPathPrefix, I as computeRank, L as normalizeRouteSegmentName, M as pushRegistrationScope, O as hasActivePageScope, R as parseSegments, S as getCurrentPageScope, _ as getCurrentInheritedAuthRequirements, b as getCurrentLayoutChain, f as addRouteToStores, p as assertRouteRegistrationUnlocked, v as getCurrentInheritedMeta, w as getCurrentScopeKind, x as getCurrentPageChain, y as getCurrentInheritedPolicies } from "./route-matching-M-f1VQRu.js";
4
4
  import { allOf } from "@askrjs/auth";
5
5
  //#region src/router/access.ts
6
6
  function compileNodePolicies(node) {
@@ -1,4 +1,4 @@
1
- import "./jsx-runtime-X2SX2y8V.js";
1
+ import "./jsx-runtime-C6Fs8Mmc.js";
2
2
  //#region src/bench/components/benchmark-row.d.ts
3
3
  interface BenchmarkRowData {
4
4
  id: number;
package/dist/benchmark.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { r as flushRuntimeScheduler } from "./access-ePqdQqkV.js";
2
- import { t as installRendererBridge } from "./renderer-CBBbYZUO.js";
2
+ import { t as installRendererBridge } from "./renderer-BJYY2Y8s.js";
3
3
  import { t as state } from "./state-CVuQVjvK.js";
4
- import { t as selector } from "./selector-DueeR6Oz.js";
4
+ import { t as selector } from "./selector-DEfqO1rA.js";
5
5
  import { jsx, jsxs } from "./jsx-runtime.js";
6
- import { i as For } from "./control-CA45Yvvu.js";
7
- import { t as createIsland } from "./boot-aTei9rjA.js";
6
+ import { i as For } from "./control-DVRBkN2X.js";
7
+ import { t as createIsland } from "./boot-DIKbEA4Y.js";
8
8
  //#region src/bench/components/benchmark-row.tsx
9
9
  function BenchmarkRow({ item, isSelected, onSelect, onRemove }) {
10
10
  return /* @__PURE__ */ jsxs("tr", {
@@ -63,8 +63,8 @@ function BenchmarkTable({ rows, isSelected, onSelect, onRemove }) {
63
63
  installRendererBridge();
64
64
  const benchmarkMetadata = {
65
65
  packageName: "@askrjs/askr",
66
- packageVersion: "0.0.69",
67
- buildLabel: "0.0.69-local"
66
+ packageVersion: "0.0.71",
67
+ buildLabel: "0.0.71-local"
68
68
  };
69
69
  function getBenchmarkMetadata() {
70
70
  return { ...benchmarkMetadata };
@@ -1,7 +1,7 @@
1
1
  import { s as ComponentFunction } from "../control-DO-iBEtV.js";
2
2
  import { v as DataRuntime } from "../index-Bki2rqcr.js";
3
- import { N as RouteRegistry, p as RouteAuthOptions } from "../router-C0XQA62W.js";
4
- import { a as ScrollRestorationOptions } from "../navigate-CV-RDqYP.js";
3
+ import { N as RouteRegistry, p as RouteAuthOptions } from "../router-C3vENhUh.js";
4
+ import { a as ScrollRestorationOptions } from "../navigate-Cbq6QHVl.js";
5
5
  //#region src/boot/types.d.ts
6
6
  type IslandConfig = {
7
7
  root: Element | string;
@@ -1,2 +1,2 @@
1
- import { a as cleanupApp, i as hydrateSPA, n as createIslands, o as hasApp, r as createSPA, t as createIsland } from "../boot-aTei9rjA.js";
1
+ import { a as cleanupApp, i as hydrateSPA, n as createIslands, o as hasApp, r as createSPA, t as createIsland } from "../boot-DIKbEA4Y.js";
2
2
  export { cleanupApp, createIsland, createIslands, createSPA, hasApp, hydrateSPA };
@@ -3,16 +3,17 @@ import { n as Fragment, t as ELEMENT_TYPE } from "./jsx-CUpRxrLH.js";
3
3
  import { n as createComponentInstance, r as executeComponent } from "./component-internal-CPjM4n8M.js";
4
4
  import { t as cleanupComponent } from "./component-cleanup-1ZFoLLHt.js";
5
5
  import { p as isPromiseLike } from "./lifecycle-batch-COgl8jMS.js";
6
- import { a as withIntrinsicHydrationAdoption, c as beginHydrationListenerTransaction, d as setStaticChildSlotsCacheEnabled, i as registerDeferredHydrationBoundary, l as commitHydrationListenerTransaction, n as activateHydrationBoundary$1, o as beginHydrationDirectListenerMode, r as clearDeferredHydrationBoundaries, s as endHydrationDirectListenerMode, t as installRendererBridge, u as discardHydrationListenerTransaction } from "./renderer-CBBbYZUO.js";
7
- import { _ as teardownNodeSubtree, d as removeAllListeners } from "./cleanup-UyStxIHG.js";
8
- import { c as _applyManifest, d as getRouteRenderContext, f as getRouteRenderData, m as resolveRouteRequest, o as reviveDeferredValue, p as hasRouteRenderData, v as pageRenderEnvelope, w as assertExecutionModel } from "./deferred-zHtUheIQ.js";
6
+ import { a as withIntrinsicHydrationAdoption, c as beginHydrationListenerTransaction, d as setStaticChildSlotsCacheEnabled, i as registerDeferredHydrationBoundary, l as commitHydrationListenerTransaction, n as activateHydrationBoundary$1, o as beginHydrationDirectListenerMode, r as clearDeferredHydrationBoundaries, s as endHydrationDirectListenerMode, t as installRendererBridge, u as discardHydrationListenerTransaction } from "./renderer-BJYY2Y8s.js";
7
+ import { _ as teardownNodeSubtree, d as removeAllListeners } from "./cleanup-D8Ufd9Ix.js";
8
+ import { c as _applyManifest, d as getRouteRenderContext, f as getRouteRenderData, m as resolveRouteRequest, o as reviveDeferredValue, p as hasRouteRenderData, v as pageRenderEnvelope, w as assertExecutionModel } from "./deferred-Cr58yIQD.js";
9
9
  import { a as startHydrationRenderPhase, s as stopHydrationRenderPhase } from "./render-context-Clw3rFiO.js";
10
- import { a as disposeDefaultPortalScope, t as DefaultPortal } from "./portal-D7TC986A.js";
11
- import { r as validateCspNonce, t as CspNonceScope } from "./csp-nonce-HGZ0vbqT.js";
12
- import { i as getDefaultDataRuntime } from "./data-runtime-SJ1BSUvk.js";
13
- import { a as hydrateDataRuntime } from "./query-registry-CQIT4mXr.js";
14
- import { d as _setActiveRouteAuthOptions, j as lockRouteRegistration, k as hasRegisteredRoutes, m as clearRouteState } from "./route-matching-DLBWDeXX.js";
15
- import { f as registerAppInstance, g as unregisterAppInstance, i as resolveRouteMeta, o as configureScrollRestoration, r as reconcileRouteMeta, t as initializeNavigation, v as setServerLocation, y as createAppRenderRuntime } from "./navigate-DpR-cML9.js";
10
+ import { d as _setActiveRouteAuthOptions, j as lockRouteRegistration, k as hasRegisteredRoutes, m as clearRouteState } from "./route-matching-M-f1VQRu.js";
11
+ import { a as disposeDefaultPortalScope, t as DefaultPortal } from "./portal-wY3j0vvp.js";
12
+ import { r as validateCspNonce, t as CspNonceScope } from "./csp-nonce-CwSRP3Jl.js";
13
+ import { i as getDefaultDataRuntime } from "./data-runtime-rpV6-3XW.js";
14
+ import { a as hydrateDataRuntime } from "./query-registry-Bu_cuMch.js";
15
+ import { o as createAppRenderRuntime, r as setServerLocation } from "./activity-C2tPn9Fr.js";
16
+ import { f as registerAppInstance, g as unregisterAppInstance, i as resolveRouteMeta, o as configureScrollRestoration, r as reconcileRouteMeta, t as initializeNavigation } from "./navigate-CuGQzS_Y.js";
16
17
  import "./ssr-CbQO5xd3.js";
17
18
  //#region src/boot/hydration.ts
18
19
  const DEFERRED_PAYLOAD = "__askr_deferred__";
@@ -584,7 +585,7 @@ async function hydrateSPA(config) {
584
585
  cspNonce: config.cspNonce
585
586
  }));
586
587
  if (shouldVerifyHydrationMarkup(config)) {
587
- const { verifyHydrationSyncForUrl } = await import("./verify-hydration-ChyEiBAn.js");
588
+ const { verifyHydrationSyncForUrl } = await import("./verify-hydration-CVSGv6Vs.js");
588
589
  if (!verifyHydrationSyncForUrl({
589
590
  root: rootElement,
590
591
  url: currentUrl,
@@ -36,6 +36,13 @@ const DELEGATED_EVENTS = [
36
36
  "touchmove",
37
37
  "touchcancel"
38
38
  ];
39
+ function createDelegatedEventFacade(event, currentTarget) {
40
+ return new Proxy(event, { get(target, property, receiver) {
41
+ if (property === "currentTarget") return currentTarget;
42
+ const value = Reflect.get(target, property, target);
43
+ return typeof value === "function" ? value.bind(target) : value;
44
+ } });
45
+ }
39
46
  const DELEGATED_HANDLERS = Symbol("askr.delegated-handlers");
40
47
  const delegatedHandlerFallback = /* @__PURE__ */ new WeakMap();
41
48
  function getDelegatedHandlerStore(element) {
@@ -94,22 +101,36 @@ function attachDelegatedListener(container, element, eventName, handler, origina
94
101
  const delegatedHandler = (e) => {
95
102
  runRuntimeHandlerScope(() => {
96
103
  const path = [];
97
- if (typeof e.composedPath === "function") path.push(...e.composedPath());
98
- else {
99
- let node = e.target;
100
- while (node) {
104
+ const seenPathNodes = /* @__PURE__ */ new Set();
105
+ let node = e.target;
106
+ while (node) {
107
+ if (!seenPathNodes.has(node)) {
108
+ seenPathNodes.add(node);
101
109
  path.push(node);
102
- if (node === container) break;
103
- node = isElementNode(node) ? node.parentNode : node.parentNode;
104
110
  }
111
+ if (node === container) break;
112
+ node = isElementNode(node) ? node.parentNode : node.parentNode;
105
113
  }
114
+ if (typeof e.composedPath === "function") {
115
+ for (const composedNode of e.composedPath()) if (!seenPathNodes.has(composedNode)) {
116
+ seenPathNodes.add(composedNode);
117
+ path.push(composedNode);
118
+ }
119
+ }
120
+ const dispatchPath = [];
106
121
  for (const node of path) {
107
122
  if (node === container) break;
108
123
  if (!isElementNode(node)) continue;
109
124
  const store = getDelegatedHandlerStore(node);
110
125
  const entry = !store ? void 0 : store instanceof Map ? store.get(eventName) : store.eventName === eventName ? store : void 0;
111
- if (entry) try {
112
- entry.handler(e);
126
+ if (entry) dispatchPath.push({
127
+ node,
128
+ entry
129
+ });
130
+ }
131
+ for (const { node, entry } of dispatchPath) {
132
+ try {
133
+ entry.handler(createDelegatedEventFacade(e, node));
113
134
  } catch (error) {
114
135
  logger.error("[Askr] Delegated event error:", error);
115
136
  }
@@ -12,6 +12,7 @@ interface ErrorBoundaryProps extends Props {
12
12
  }
13
13
  //#endregion
14
14
  //#region src/components/error-boundary.d.ts
15
+ /** Creates a render-time boundary whose fallback handles descendant render/commit errors. */
15
16
  declare function ErrorBoundary(props: ErrorBoundaryProps): JSXElement;
16
17
  //#endregion
17
18
  export { ErrorBoundary, type ErrorBoundaryFallbackRender, type ErrorBoundaryProps };
@@ -30,6 +30,7 @@ function createBoundaryVNode(instance, props) {
30
30
  __instance: instance
31
31
  };
32
32
  }
33
+ /** Creates a render-time boundary whose fallback handles descendant render/commit errors. */
33
34
  function ErrorBoundary(props) {
34
35
  const instance = getCurrentComponentInstance();
35
36
  if (!instance) throw new Error("[Askr] ErrorBoundary() can only be used during component render execution.");
@@ -1,2 +1,2 @@
1
- import { a as Show, c as ForProps, i as MatchProps, n as CaseProps, o as ShowProps, r as Match, s as For, t as Case } from "../index-Dh6ZF9yW.js";
1
+ import { a as Show, c as ForProps, i as MatchProps, n as CaseProps, o as ShowProps, r as Match, s as For, t as Case } from "../index-UmwPZ8ZN.js";
2
2
  export { Case, type CaseProps, For, type ForProps, Match, type MatchProps, Show, type ShowProps };
@@ -1,2 +1,2 @@
1
- import { i as For, n as Match, r as Show, t as Case } from "../control-CA45Yvvu.js";
1
+ import { i as For, n as Match, r as Show, t as Case } from "../control-DVRBkN2X.js";
2
2
  export { Case, For, Match, Show };
@@ -22,9 +22,14 @@ function resolveMaybeAccessor(value) {
22
22
  //#endregion
23
23
  //#region src/control/for.ts
24
24
  /**
25
- * For JSX primitive
25
+ * Render a reactive list as keyed child scopes.
26
26
  *
27
- * Creates a keyed child-scope boundary for efficient list rendering.
27
+ * The `children` callback receives a snapshot item during boundary
28
+ * reconciliation. A plain closure read of parent state is therefore not a
29
+ * dependency of an existing row. Use `selector(() => value())` for keyed
30
+ * membership reads, or a function-valued prop when only a DOM property needs
31
+ * to update. See the reactive control-flow guide for the supported patterns:
32
+ * https://github.com/askrjs/askr/blob/main/docs/guides/control-flow.md
28
33
  */
29
34
  function resolveEach(each) {
30
35
  const resolved = typeof each === "function" ? each() : each;
@@ -1,4 +1,19 @@
1
1
  import { h as readScope, u as defineScope } from "./component-internal-CPjM4n8M.js";
2
+ //#region src/common/url.ts
3
+ const SAFE_URL_SCHEMES = /* @__PURE__ */ new Set([
4
+ "http",
5
+ "https",
6
+ "mailto",
7
+ "sms",
8
+ "tel"
9
+ ]);
10
+ const URL_SCHEME_RE = /^([a-z][a-z0-9+.-]*):/i;
11
+ function isSafeHref(value) {
12
+ const compact = value.trim().replace(/[\u0000-\u0020\u007f-\u009f]/g, "");
13
+ const scheme = URL_SCHEME_RE.exec(compact)?.[1]?.toLowerCase();
14
+ return scheme === void 0 || SAFE_URL_SCHEMES.has(scheme);
15
+ }
16
+ //#endregion
2
17
  //#region src/common/router-internal.ts
3
18
  const ROUTE_ROOT_COMPONENT = Symbol.for("askr.route-root-component");
4
19
  //#endregion
@@ -30,4 +45,4 @@ function validateCspNonce(value) {
30
45
  return value;
31
46
  }
32
47
  //#endregion
33
- export { ROUTE_ROOT_COMPONENT as i, cspNonce as n, validateCspNonce as r, CspNonceScope as t };
48
+ export { isSafeHref as a, ROUTE_ROOT_COMPONENT as i, cspNonce as n, validateCspNonce as r, CspNonceScope as t };
@@ -0,0 +1,70 @@
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
+ //#region src/common/css.ts
16
+ const CSS_UNSAFE_RE = /[{}<>\\]/g;
17
+ const CSS_URI_SCHEME_RE = /(?:^|[\s(,])([a-z][a-z0-9+.-]*):/i;
18
+ const CSS_FUNCTION_NAME_RE = /([a-z-][a-z0-9-]*)\s*\(/gi;
19
+ const CSS_ALLOWED_FUNCTIONS = /* @__PURE__ */ new Set([
20
+ "var",
21
+ "calc",
22
+ "min",
23
+ "max",
24
+ "clamp",
25
+ "rgb",
26
+ "rgba",
27
+ "hsl",
28
+ "hsla",
29
+ "lab",
30
+ "lch",
31
+ "oklab",
32
+ "oklch",
33
+ "color",
34
+ "color-mix",
35
+ "translate",
36
+ "translatex",
37
+ "translatey",
38
+ "translatez",
39
+ "scale",
40
+ "scalex",
41
+ "scaley",
42
+ "scalez",
43
+ "rotate",
44
+ "rotatex",
45
+ "rotatey",
46
+ "rotatez",
47
+ "skew",
48
+ "skewx",
49
+ "skewy",
50
+ "matrix",
51
+ "matrix3d",
52
+ "linear-gradient",
53
+ "radial-gradient",
54
+ "conic-gradient",
55
+ "repeating-linear-gradient",
56
+ "repeating-radial-gradient",
57
+ "repeating-conic-gradient",
58
+ "cubic-bezier",
59
+ "steps"
60
+ ]);
61
+ function sanitizeCssValue(value) {
62
+ const str = String(value);
63
+ if (CSS_URI_SCHEME_RE.test(str)) return "";
64
+ if (str.includes("(")) {
65
+ for (const match of str.matchAll(CSS_FUNCTION_NAME_RE)) if (!CSS_ALLOWED_FUNCTIONS.has(match[1].toLowerCase())) return "";
66
+ }
67
+ return str.replace(CSS_UNSAFE_RE, "");
68
+ }
69
+ //#endregion
70
+ export { getPublicAttributeName as n, sanitizeCssValue as t };
@@ -1,4 +1,4 @@
1
- import { i as getDefaultDataRuntime, t as createDataRuntime } from "../data-runtime-SJ1BSUvk.js";
2
- import { a as queryScope, i as invalidateOnInterval, n as createMutation, r as invalidate, t as createQuery } from "../data-DHt_zO1G.js";
3
- import { a as hydrateDataRuntime, i as dehydrateDataRuntime, n as defineQuery, o as prefetchQuery, r as defineServerQueries, s as serveQuery, t as createQueryPrefetchContext } from "../query-registry-CQIT4mXr.js";
1
+ import { i as getDefaultDataRuntime, t as createDataRuntime } from "../data-runtime-rpV6-3XW.js";
2
+ import { a as queryScope, i as invalidateOnInterval, n as createMutation, r as invalidate, t as createQuery } from "../data-DFcSmGvN.js";
3
+ import { a as hydrateDataRuntime, i as dehydrateDataRuntime, n as defineQuery, o as prefetchQuery, r as defineServerQueries, s as serveQuery, t as createQueryPrefetchContext } from "../query-registry-Bu_cuMch.js";
4
4
  export { createDataRuntime, createMutation, createQuery, createQueryPrefetchContext, defineQuery, defineServerQueries, dehydrateDataRuntime, getDefaultDataRuntime, hydrateDataRuntime, invalidate, invalidateOnInterval, prefetchQuery, queryScope, serveQuery };
@@ -2,8 +2,8 @@ import { n as enqueueRuntimeTask, v as logger } from "./access-ePqdQqkV.js";
2
2
  import { l as notifyReadableReaders, o as markReactivePropsDirtySource, s as markReadableDerivedSubscribersDirty, u as recordReadableRead } from "./readable-BYSoWJSv.js";
3
3
  import { f as getCurrentComponentInstance, i as claimHookIndex } from "./component-scope-CC3cojX9.js";
4
4
  import { n as getActiveRenderContext } from "./render-context-Clw3rFiO.js";
5
- import { c as windowFocused, i as routeActive, n as documentVisible, s as timer } from "./lifecycle-operations-SlPEK68H.js";
6
- import { a as getMutationSlotStore, c as resolveDataRuntimeState, i as getDefaultDataRuntime, n as ensureMutationCleanup, o as getQuerySlotStore, r as ensureQueryCleanup, s as invalidateQueriesForRuntime } from "./data-runtime-SJ1BSUvk.js";
5
+ import { i as routeActive, n as documentVisible, o as timer, s as windowFocused } from "./lifecycle-operations-Db-_MG-O.js";
6
+ import { a as getMutationSlotStore, c as resolveDataRuntimeState, i as getDefaultDataRuntime, n as ensureMutationCleanup, o as getQuerySlotStore, r as ensureQueryCleanup, s as invalidateQueriesForRuntime } from "./data-runtime-rpV6-3XW.js";
7
7
  //#region src/data/query-key.ts
8
8
  function serializeQueryKeyNumber(part) {
9
9
  if (Number.isNaN(part)) return "NaN";
@@ -1,5 +1,16 @@
1
1
  import { n as getActiveRenderContext } from "./render-context-Clw3rFiO.js";
2
- import { n as emitInvalidation } from "./invalidation-listeners-Des3AHYs.js";
2
+ //#region src/data/invalidation-listeners.ts
3
+ const invalidationListeners = /* @__PURE__ */ new Set();
4
+ function addInvalidationListener(listener) {
5
+ invalidationListeners.add(listener);
6
+ return () => {
7
+ invalidationListeners.delete(listener);
8
+ };
9
+ }
10
+ function emitInvalidation(event) {
11
+ for (const listener of invalidationListeners) listener(event);
12
+ }
13
+ //#endregion
3
14
  //#region src/data/data-runtime.ts
4
15
  const dataRuntimeStates = /* @__PURE__ */ new WeakMap();
5
16
  const dataRuntimeByQueryCache = /* @__PURE__ */ new WeakMap();
@@ -110,4 +121,4 @@ function invalidateQueriesForRuntime(runtimeState, prefix, markPendingWrite) {
110
121
  }
111
122
  }
112
123
  //#endregion
113
- export { getMutationSlotStore as a, resolveDataRuntimeState as c, getDefaultDataRuntime as i, ensureMutationCleanup as n, getQuerySlotStore as o, ensureQueryCleanup as r, invalidateQueriesForRuntime as s, createDataRuntime as t };
124
+ export { getMutationSlotStore as a, resolveDataRuntimeState as c, getDefaultDataRuntime as i, addInvalidationListener as l, ensureMutationCleanup as n, getQuerySlotStore as o, ensureQueryCleanup as r, invalidateQueriesForRuntime as s, createDataRuntime as t };
@@ -3,10 +3,9 @@ import { h as readScope, u as defineScope } from "./component-internal-CPjM4n8M.
3
3
  import { d as getCurrentAppRenderRuntime } from "./component-scope-CC3cojX9.js";
4
4
  import { p as isPromiseLike } from "./lifecycle-batch-COgl8jMS.js";
5
5
  import { n as getActiveRenderContext, r as getCurrentRenderData } from "./render-context-Clw3rFiO.js";
6
- import { t as resource } from "./resource-operation-BJiLoLYZ.js";
7
- import { i as ROUTE_ROOT_COMPONENT } from "./csp-nonce-HGZ0vbqT.js";
8
- import { c as withTelemetry, t as createQueryPrefetchContext } from "./query-registry-CQIT4mXr.js";
9
- import { A as insertRecordSorted, D as getRouteRecords, E as getRouteList, F as snapshotRouteState, N as restoreRouteState, P as setDefaultRouteAuthOptions, T as getDefaultRouteAuthOptions, f as addRouteToStores, h as getActiveRouteAuthOptions, i as getMatchingRouteRecord, m as clearRouteState, o as buildRouteContext, s as buildRouteContextBase } from "./route-matching-DLBWDeXX.js";
6
+ import { A as insertRecordSorted, D as getRouteRecords, E as getRouteList, F as snapshotRouteState, N as restoreRouteState, P as setDefaultRouteAuthOptions, T as getDefaultRouteAuthOptions, f as addRouteToStores, h as getActiveRouteAuthOptions, i as getMatchingRouteRecord, m as clearRouteState, o as buildRouteContext, s as buildRouteContextBase, z as resource } from "./route-matching-M-f1VQRu.js";
7
+ import { i as ROUTE_ROOT_COMPONENT } from "./csp-nonce-CwSRP3Jl.js";
8
+ import { c as withTelemetry, t as createQueryPrefetchContext } from "./query-registry-Bu_cuMch.js";
10
9
  //#region src/runtime/execution-model.ts
11
10
  const EXECUTION_MODEL_KEY = Symbol.for("__ASKR_EXECUTION_MODEL__");
12
11
  function getExecutionModel() {