@askrjs/askr 0.0.85 → 0.0.87
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/CHANGELOG.md +60 -0
- package/capabilities.json +25 -0
- package/dist/actions/index.d.ts +1 -1
- package/dist/actions/index.js +2 -2
- package/dist/{activity-Jd9CgEa3.js → activity-BnkhdIXm.js} +3 -3
- package/dist/{activity-B1I5HJQI.d.ts → activity-DNYL__cW.d.ts} +1 -1
- package/dist/benchmark.js +5 -5
- package/dist/boot/index.d.ts +3 -3
- package/dist/boot/index.js +1 -1
- package/dist/{boot-DWe880Et.js → boot-Bd-j_BL5.js} +15 -14
- package/dist/{component-internal-DcrLymUJ.js → component-internal-uVCJAre6.js} +1 -1
- package/dist/control/index.js +1 -1
- package/dist/{control-oLADku43.js → control-BF3geQKh.js} +1 -1
- package/dist/{csp-nonce-Bc52OIVc.js → csp-nonce-CUscoNF1.js} +1 -1
- package/dist/data/index.d.ts +1 -1
- package/dist/data/index.js +3 -3
- package/dist/{data-Dkqb8_QP.js → data-CXZ-FOa7.js} +6 -3
- package/dist/{data-runtime-D68YOo9L.js → data-runtime-CnVeSvJz.js} +7 -5
- package/dist/default-portal-runtime-DvMvWJVp.js +20 -0
- package/dist/{authoring-DdQ3pHqt.js → deferred-_DaSfpsr.js} +81 -4
- package/dist/{for-internal-B_mnQhan.js → for-internal-Dxf3iZ9E.js} +1 -1
- package/dist/foundations/index.d.ts +1 -1
- package/dist/foundations/index.js +1 -2
- package/dist/foundations/structures/index.d.ts +1 -1
- package/dist/foundations/structures/index.js +1 -2
- package/dist/{index-pIgGaXvS.d.ts → index-BvNkcegT.d.ts} +1 -1
- package/dist/{index-Bkh9S9-t.d.ts → index-DflhL1h8.d.ts} +15 -15
- package/dist/{index-5S-fi2xy.d.ts → index-SGxMZLAc.d.ts} +3 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +7 -7
- package/dist/{lifecycle-operations-BrYrBsXY.js → lifecycle-operations-DTO93Hrl.js} +1 -1
- package/dist/manifest-D1P9uTlz.js +53 -0
- package/dist/{navigate-NyIjQUwI.d.ts → navigate-B_fcLDAG.d.ts} +1 -1
- package/dist/{navigate-b4GGxO_l.js → navigate-DSATWfHh.js} +8 -8
- package/dist/{query-registry-BL6rjGsO.js → query-registry-p_0kkieE.js} +1 -1
- package/dist/render-context-D0Hoj9dW.js +161 -0
- package/dist/{renderer-CZzNtoj2.js → renderer-BGMaUrVj.js} +10 -7
- package/dist/{deferred-vUOy-awa.js → resolution-BRmiFYvw.js} +61 -231
- package/dist/resource-operation-B94oj6xT.js +304 -0
- package/dist/resources/index.d.ts +2 -2
- package/dist/resources/index.js +4 -4
- package/dist/{route-matching-DHduNiGk.js → route-matching-DqULzZtC.js} +2 -276
- package/dist/router/index.d.ts +8 -6
- package/dist/router/index.js +7 -6
- package/dist/ssg/index.d.ts +1 -1
- package/dist/ssg/index.js +5 -4
- package/dist/ssr/index.d.ts +2 -2
- package/dist/ssr/index.js +2 -2
- package/dist/{ssr-CpiBHMNv.js → ssr-q250YlKo.js} +36 -18
- package/dist/{portal-BVWjAhNQ.js → structures-DsOm-clq.js} +232 -3
- package/dist/testing/index.d.ts +17 -3
- package/dist/testing/index.js +42 -4
- package/dist/{verify-hydration-C3QBBQqR.js → verify-hydration-DkISyZCo.js} +4 -3
- package/package.json +3 -2
- package/dist/render-context-D-DFk2WN.js +0 -73
- package/dist/structures-DSLF_iis.js +0 -223
|
@@ -1,11 +1,107 @@
|
|
|
1
1
|
import { o as getRuntimeRenderer } from "./access-Dpfoi4cA.js";
|
|
2
2
|
import { f as getCurrentComponentInstance, m as getCurrentPortalScope } from "./component-scope-DzJEbYGE.js";
|
|
3
|
-
import { t as ELEMENT_TYPE } from "./jsx-C3IECePB.js";
|
|
3
|
+
import { n as Fragment, t as ELEMENT_TYPE } from "./jsx-C3IECePB.js";
|
|
4
4
|
import { l as notifyReadableReaders, o as markReactivePropsDirtySource, s as markReadableDerivedSubscribersDirty, u as recordReadableRead } from "./readable-B5NtV7V0.js";
|
|
5
5
|
import { t as cleanupComponent } from "./component-cleanup-BUfUleGZ.js";
|
|
6
6
|
import { c as getCurrentLifecycleCommitBatch, u as registerLifecycleTransaction } from "./lifecycle-batch-Dfpid9-A.js";
|
|
7
|
-
import { n as getActiveRenderContext } from "./render-context-
|
|
7
|
+
import { n as getActiveRenderContext } from "./render-context-D0Hoj9dW.js";
|
|
8
8
|
import { i as createSSRPortalHostToken, n as SSR_PORTAL_HOST, r as createSSRPortalAnchorToken, t as SSR_PORTAL_ANCHOR } from "./portal-w3oQ6oQU.js";
|
|
9
|
+
import { i as registerDefaultPortalRuntime } from "./default-portal-runtime-DvMvWJVp.js";
|
|
10
|
+
//#region src/jsx/utils.ts
|
|
11
|
+
function isElement(value) {
|
|
12
|
+
return typeof value === "object" && value !== null && value.$$typeof === ELEMENT_TYPE;
|
|
13
|
+
}
|
|
14
|
+
function cloneElement(element, props) {
|
|
15
|
+
return {
|
|
16
|
+
$$typeof: element.$$typeof,
|
|
17
|
+
type: element.type,
|
|
18
|
+
key: element.key,
|
|
19
|
+
props: {
|
|
20
|
+
...element.props,
|
|
21
|
+
...props
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/foundations/structures/layout.tsx
|
|
27
|
+
function layout(Layout) {
|
|
28
|
+
return (children, props) => {
|
|
29
|
+
return Layout({
|
|
30
|
+
...props,
|
|
31
|
+
children
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/foundations/structures/slot.tsx
|
|
37
|
+
/**
|
|
38
|
+
* Slot
|
|
39
|
+
*
|
|
40
|
+
* Structural primitive for prop forwarding patterns.
|
|
41
|
+
*
|
|
42
|
+
* POLICY DECISIONS (LOCKED):
|
|
43
|
+
*
|
|
44
|
+
* 1. asChild Pattern
|
|
45
|
+
* When asChild=true, merges props into the single child element.
|
|
46
|
+
* Child must be a valid JSXElement; non-element children return null.
|
|
47
|
+
* **Slot props override child props** (injection pattern).
|
|
48
|
+
*
|
|
49
|
+
* 2. Fallback Behavior
|
|
50
|
+
* When asChild=false, returns a Fragment (structural no-op).
|
|
51
|
+
* No DOM element is introduced.
|
|
52
|
+
*
|
|
53
|
+
* 3. Type Safety
|
|
54
|
+
* asChild=true requires exactly one JSXElement child (enforced by type).
|
|
55
|
+
* Runtime validates with isElement() check.
|
|
56
|
+
*/
|
|
57
|
+
function Slot(props) {
|
|
58
|
+
if (props.asChild) {
|
|
59
|
+
const { children, asChild: _asChild, ...rest } = props;
|
|
60
|
+
if (isElement(children)) return cloneElement(children, rest);
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
$$typeof: ELEMENT_TYPE,
|
|
65
|
+
type: Fragment,
|
|
66
|
+
props: { children: props.children },
|
|
67
|
+
key: null
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region src/foundations/structures/presence.ts
|
|
72
|
+
/**
|
|
73
|
+
* Presence
|
|
74
|
+
*
|
|
75
|
+
* Structural policy primitive for conditional mount/unmount.
|
|
76
|
+
* - No timers
|
|
77
|
+
* - No animation coupling
|
|
78
|
+
* - No DOM side-effects
|
|
79
|
+
*
|
|
80
|
+
* POLICY DECISIONS (LOCKED):
|
|
81
|
+
*
|
|
82
|
+
* 1. Present as Function
|
|
83
|
+
* Accepts boolean OR function to support lazy evaluation patterns.
|
|
84
|
+
* Function is called once per render. Use boolean form for static values.
|
|
85
|
+
*
|
|
86
|
+
* 2. Children Type
|
|
87
|
+
* Presence forwards normal renderable child content only.
|
|
88
|
+
* Imperative DOM nodes are not part of the public contract.
|
|
89
|
+
*
|
|
90
|
+
* 3. Immediate Mount/Unmount
|
|
91
|
+
* No exit animations or transitions. When `present` becomes false,
|
|
92
|
+
* children are removed immediately. Animation must be layered above
|
|
93
|
+
* this primitive.
|
|
94
|
+
*/
|
|
95
|
+
function Presence({ present, children }) {
|
|
96
|
+
if (!(typeof present === "function" ? present() : Boolean(present))) return null;
|
|
97
|
+
return {
|
|
98
|
+
$$typeof: ELEMENT_TYPE,
|
|
99
|
+
type: Fragment,
|
|
100
|
+
props: { children },
|
|
101
|
+
key: null
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
//#endregion
|
|
9
105
|
//#region src/runtime/portal.ts
|
|
10
106
|
const DEFAULT_SSR_PORTAL_KEY = {};
|
|
11
107
|
function getSSRPortalSlot(key) {
|
|
@@ -391,5 +487,138 @@ function Portal(props) {
|
|
|
391
487
|
writeDefaultPortal(props, owner);
|
|
392
488
|
return null;
|
|
393
489
|
}
|
|
490
|
+
registerDefaultPortalRuntime({
|
|
491
|
+
host: DefaultPortal,
|
|
492
|
+
clearForInstance(instance) {
|
|
493
|
+
clearDefaultPortalForInstance(instance);
|
|
494
|
+
},
|
|
495
|
+
disposeScope: disposeDefaultPortalScope
|
|
496
|
+
});
|
|
497
|
+
//#endregion
|
|
498
|
+
//#region src/foundations/structures/collection.ts
|
|
499
|
+
function createCollection() {
|
|
500
|
+
const registry = /* @__PURE__ */ new Map();
|
|
501
|
+
function register(node, metadata) {
|
|
502
|
+
const item = {
|
|
503
|
+
node,
|
|
504
|
+
metadata
|
|
505
|
+
};
|
|
506
|
+
registry.set(node, item);
|
|
507
|
+
return () => {
|
|
508
|
+
registry.delete(node);
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
function items() {
|
|
512
|
+
return Array.from(registry.values());
|
|
513
|
+
}
|
|
514
|
+
function clear() {
|
|
515
|
+
registry.clear();
|
|
516
|
+
}
|
|
517
|
+
function size() {
|
|
518
|
+
return registry.size;
|
|
519
|
+
}
|
|
520
|
+
return {
|
|
521
|
+
register,
|
|
522
|
+
items,
|
|
523
|
+
clear,
|
|
524
|
+
size
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* USAGE EXAMPLE:
|
|
529
|
+
*
|
|
530
|
+
* // Create a collection for menu items
|
|
531
|
+
* const menuItems = createCollection<HTMLElement, { disabled: boolean }>();
|
|
532
|
+
*
|
|
533
|
+
* // Register items
|
|
534
|
+
* const unregister1 = menuItems.register(element1, { disabled: false });
|
|
535
|
+
* const unregister2 = menuItems.register(element2, { disabled: true });
|
|
536
|
+
*
|
|
537
|
+
* // Query items
|
|
538
|
+
* const allItems = menuItems.items();
|
|
539
|
+
* const enabledItems = allItems.filter(item => !item.metadata.disabled);
|
|
540
|
+
*
|
|
541
|
+
* // Cleanup
|
|
542
|
+
* unregister1();
|
|
543
|
+
* unregister2();
|
|
544
|
+
*/
|
|
545
|
+
//#endregion
|
|
546
|
+
//#region src/foundations/structures/layer.ts
|
|
547
|
+
function createLayer() {
|
|
548
|
+
const stack = [];
|
|
549
|
+
let nextId = 1;
|
|
550
|
+
function register(options) {
|
|
551
|
+
const id = nextId++;
|
|
552
|
+
const entry = {
|
|
553
|
+
id,
|
|
554
|
+
options
|
|
555
|
+
};
|
|
556
|
+
stack.push(entry);
|
|
557
|
+
function isTop() {
|
|
558
|
+
return stack[stack.length - 1]?.id === id;
|
|
559
|
+
}
|
|
560
|
+
function unregister() {
|
|
561
|
+
const index = stack.findIndex((e) => e.id === id);
|
|
562
|
+
if (index !== -1) stack.splice(index, 1);
|
|
563
|
+
}
|
|
564
|
+
return {
|
|
565
|
+
id,
|
|
566
|
+
isTop,
|
|
567
|
+
unregister
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
function layers() {
|
|
571
|
+
return stack.map((entry) => ({
|
|
572
|
+
id: entry.id,
|
|
573
|
+
isTop: () => stack[stack.length - 1]?.id === entry.id,
|
|
574
|
+
unregister: () => {
|
|
575
|
+
const index = stack.findIndex((e) => e.id === entry.id);
|
|
576
|
+
if (index !== -1) stack.splice(index, 1);
|
|
577
|
+
}
|
|
578
|
+
}));
|
|
579
|
+
}
|
|
580
|
+
function handleEscape() {
|
|
581
|
+
const top = stack[stack.length - 1];
|
|
582
|
+
if (top) top.options.onEscape?.();
|
|
583
|
+
}
|
|
584
|
+
function handleOutsidePointer(e) {
|
|
585
|
+
const top = stack[stack.length - 1];
|
|
586
|
+
if (!top) return;
|
|
587
|
+
const node = top.options.node;
|
|
588
|
+
if (node && e.target instanceof Node) {
|
|
589
|
+
if (!node.contains(e.target)) top.options.onOutsidePointer?.(e);
|
|
590
|
+
} else top.options.onOutsidePointer?.(e);
|
|
591
|
+
}
|
|
592
|
+
return {
|
|
593
|
+
register,
|
|
594
|
+
layers,
|
|
595
|
+
handleEscape,
|
|
596
|
+
handleOutsidePointer
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* USAGE EXAMPLE:
|
|
601
|
+
*
|
|
602
|
+
* const layerManager = createLayer();
|
|
603
|
+
*
|
|
604
|
+
* function Modal({ onClose }) {
|
|
605
|
+
* const modalRef = ref<HTMLDivElement>();
|
|
606
|
+
*
|
|
607
|
+
* const layer = layerManager.register({
|
|
608
|
+
* node: modalRef.current,
|
|
609
|
+
* onEscape: onClose,
|
|
610
|
+
* onOutsidePointer: onClose,
|
|
611
|
+
* });
|
|
612
|
+
*
|
|
613
|
+
* onUnmount(() => layer.unregister());
|
|
614
|
+
*
|
|
615
|
+
* return (
|
|
616
|
+
* <div ref={modalRef}>
|
|
617
|
+
* <h1>Modal</h1>
|
|
618
|
+
* {layer.isTop() && <p>I am on top!</p>}
|
|
619
|
+
* </div>
|
|
620
|
+
* );
|
|
621
|
+
* }
|
|
622
|
+
*/
|
|
394
623
|
//#endregion
|
|
395
|
-
export {
|
|
624
|
+
export { definePortal as a, layout as c, Portal as i, cloneElement as l, createCollection as n, Presence as o, DefaultPortal as r, Slot as s, createLayer as t, isElement as u };
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { l as ComponentFunction } from "../control-DhUZU4_V.js";
|
|
2
|
-
import { M as RouteMatch, W as RouteRegistry, w as RouteAuthOptions } from "../index-
|
|
3
|
-
import { C as Query, k as QueryStaleReason } from "../index-
|
|
2
|
+
import { M as RouteMatch, W as RouteRegistry, w as RouteAuthOptions } from "../index-BvNkcegT.js";
|
|
3
|
+
import { C as Query, k as QueryStaleReason, v as DataRuntime } from "../index-SGxMZLAc.js";
|
|
4
4
|
//#region src/testing/render.d.ts
|
|
5
5
|
interface RenderOptions {
|
|
6
6
|
/**
|
|
@@ -34,6 +34,20 @@ declare function mount(component: ComponentFunction, options?: RenderOptions): R
|
|
|
34
34
|
declare function renderRoute(options: RouteRenderOptions): Promise<RenderResult>;
|
|
35
35
|
//#endregion
|
|
36
36
|
//#region src/testing/index.d.ts
|
|
37
|
+
/** Dispatch the browser click sequence expected by Askr's delegated events. */
|
|
38
|
+
declare function click(element: Element): boolean;
|
|
39
|
+
/** Set a text control's value and emit an input event for each character. */
|
|
40
|
+
declare function type(element: HTMLInputElement | HTMLTextAreaElement, text: string): void;
|
|
41
|
+
/** Dispatch a cancelable bubbling submit event on a form. */
|
|
42
|
+
declare function submit(form: HTMLFormElement): boolean;
|
|
43
|
+
interface QueryTestRegistry {
|
|
44
|
+
readonly runtime: DataRuntime;
|
|
45
|
+
set<T extends {}>(key: string, query: Query<T>): void;
|
|
46
|
+
delete(key: string): void;
|
|
47
|
+
clear(): void;
|
|
48
|
+
}
|
|
49
|
+
/** Create a keyed query fixture registry for a test render runtime. */
|
|
50
|
+
declare function createQueryTestRegistry(): QueryTestRegistry;
|
|
37
51
|
type MockRefresh = () => void | Promise<void>;
|
|
38
52
|
interface MockQueryOptions {
|
|
39
53
|
refresh?: MockRefresh;
|
|
@@ -80,4 +94,4 @@ declare function createInvalidationRecorder(): InvalidationRecorder;
|
|
|
80
94
|
declare function matchRoute(path: string, options: MatchRouteOptions): RouteMatch | null;
|
|
81
95
|
declare function getRouteWarnings(options: MatchRouteOptions): RoutePatternWarning[];
|
|
82
96
|
//#endregion
|
|
83
|
-
export { InvalidationRecord, InvalidationRecorder, MockQueryOptions, MockRefresh, type RenderOptions, type RenderResult, RoutePatternWarning, type RouteRenderOptions, cleanup, createInvalidationRecorder, dispatch, flush, getRouteWarnings, matchRoute, mockQuery, mount, queryState, render, renderRoute };
|
|
97
|
+
export { InvalidationRecord, InvalidationRecorder, MockQueryOptions, MockRefresh, QueryTestRegistry, type RenderOptions, type RenderResult, RoutePatternWarning, type RouteRenderOptions, cleanup, click, createInvalidationRecorder, createQueryTestRegistry, dispatch, flush, getRouteWarnings, matchRoute, mockQuery, mount, queryState, render, renderRoute, submit, type };
|
package/dist/testing/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { r as flushRuntimeScheduler } from "../access-Dpfoi4cA.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { a as cleanupApp, r as createSPA, t as createIsland } from "../boot-
|
|
2
|
+
import { l as addInvalidationListener, t as createDataRuntime } from "../data-runtime-CnVeSvJz.js";
|
|
3
|
+
import { r as computeRouteActivityMatches } from "../route-matching-DqULzZtC.js";
|
|
4
|
+
import { a as cleanupApp, r as createSPA, t as createIsland } from "../boot-Bd-j_BL5.js";
|
|
5
5
|
//#region src/testing/render.ts
|
|
6
6
|
const renderStates = /* @__PURE__ */ new WeakMap();
|
|
7
7
|
const eventConstructorNames = {
|
|
@@ -180,6 +180,44 @@ async function renderRoute(options) {
|
|
|
180
180
|
}
|
|
181
181
|
//#endregion
|
|
182
182
|
//#region src/testing/index.ts
|
|
183
|
+
/** Dispatch the browser click sequence expected by Askr's delegated events. */
|
|
184
|
+
function click(element) {
|
|
185
|
+
if (!element || typeof element.dispatchEvent !== "function") throw new TypeError("@askrjs/askr/testing click requires an Element.");
|
|
186
|
+
return dispatch(element, "click");
|
|
187
|
+
}
|
|
188
|
+
/** Set a text control's value and emit an input event for each character. */
|
|
189
|
+
function type(element, text) {
|
|
190
|
+
if (!element || typeof element.dispatchEvent !== "function") throw new TypeError("@askrjs/askr/testing type requires a text control.");
|
|
191
|
+
for (const character of text) {
|
|
192
|
+
element.value += character;
|
|
193
|
+
dispatch(element, "input", {
|
|
194
|
+
inputType: "insertText",
|
|
195
|
+
data: character
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/** Dispatch a cancelable bubbling submit event on a form. */
|
|
200
|
+
function submit(form) {
|
|
201
|
+
if (!form || typeof form.dispatchEvent !== "function") throw new TypeError("@askrjs/askr/testing submit requires a form.");
|
|
202
|
+
return dispatch(form, "submit");
|
|
203
|
+
}
|
|
204
|
+
/** Create a keyed query fixture registry for a test render runtime. */
|
|
205
|
+
function createQueryTestRegistry() {
|
|
206
|
+
const runtime = createDataRuntime();
|
|
207
|
+
return {
|
|
208
|
+
runtime,
|
|
209
|
+
set(key, query) {
|
|
210
|
+
if (typeof key !== "string" || key.length === 0) throw new TypeError("@askrjs/askr/testing query registry keys must be non-empty strings.");
|
|
211
|
+
runtime.queryTestOverrides.set(key, query);
|
|
212
|
+
},
|
|
213
|
+
delete(key) {
|
|
214
|
+
runtime.queryTestOverrides.delete(key);
|
|
215
|
+
},
|
|
216
|
+
clear() {
|
|
217
|
+
runtime.queryTestOverrides.clear();
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
}
|
|
183
221
|
function normalizeRefresh(options) {
|
|
184
222
|
return async () => {
|
|
185
223
|
await options?.refresh?.();
|
|
@@ -342,4 +380,4 @@ function getRouteWarnings(options) {
|
|
|
342
380
|
});
|
|
343
381
|
}
|
|
344
382
|
//#endregion
|
|
345
|
-
export { cleanup, createInvalidationRecorder, dispatch, flush, getRouteWarnings, matchRoute, mockQuery, mount, queryState, render, renderRoute };
|
|
383
|
+
export { cleanup, click, createInvalidationRecorder, createQueryTestRegistry, dispatch, flush, getRouteWarnings, matchRoute, mockQuery, mount, queryState, render, renderRoute, submit, type };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { m as withHydrationVerificationRender } from "./render-context-D0Hoj9dW.js";
|
|
1
2
|
import { t as SSR_RENDER_DATA_ATTR } from "./ssr-DSHd_Q9K.js";
|
|
2
|
-
import { a as renderResolvedToStringSync } from "./ssr-
|
|
3
|
+
import { a as renderResolvedToStringSync } from "./ssr-q250YlKo.js";
|
|
3
4
|
//#region src/ssr/verify-hydration.ts
|
|
4
5
|
function normalizeHydrationHtml(html) {
|
|
5
6
|
const template = document.createElement("template");
|
|
@@ -9,13 +10,13 @@ function normalizeHydrationHtml(html) {
|
|
|
9
10
|
}
|
|
10
11
|
function verifyHydrationSyncForUrl(opts) {
|
|
11
12
|
const { root, url, registry, resolved, options } = opts;
|
|
12
|
-
const expected = renderResolvedToStringSync({
|
|
13
|
+
const expected = withHydrationVerificationRender(() => renderResolvedToStringSync({
|
|
13
14
|
url,
|
|
14
15
|
registry,
|
|
15
16
|
handler: resolved.handler,
|
|
16
17
|
params: resolved.params,
|
|
17
18
|
options
|
|
18
|
-
});
|
|
19
|
+
}));
|
|
19
20
|
return normalizeHydrationHtml(root.innerHTML) === normalizeHydrationHtml(expected);
|
|
20
21
|
}
|
|
21
22
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askrjs/askr",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.87",
|
|
4
4
|
"description": "Actor-backed deterministic UI framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"askr",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"files": [
|
|
26
26
|
"capabilities.json",
|
|
27
|
+
"CHANGELOG.md",
|
|
27
28
|
"dist/**/*.js",
|
|
28
29
|
"dist/**/*.d.ts"
|
|
29
30
|
],
|
|
@@ -170,7 +171,7 @@
|
|
|
170
171
|
}
|
|
171
172
|
},
|
|
172
173
|
"engines": {
|
|
173
|
-
"node": ">=24.
|
|
174
|
+
"node": ">=24.0.0"
|
|
174
175
|
},
|
|
175
176
|
"packageManager": "npm@12.0.1",
|
|
176
177
|
"allowScripts": {
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
//#region src/common/ssr-errors.ts
|
|
2
|
-
/**
|
|
3
|
-
* Common call contracts: SSR error types
|
|
4
|
-
*/
|
|
5
|
-
var SSRDataMissingError = class SSRDataMissingError extends Error {
|
|
6
|
-
constructor(message = "Server-side rendering requires all data to be available synchronously. This component attempted to use async data during SSR.") {
|
|
7
|
-
super(message);
|
|
8
|
-
this.code = "SSR_DATA_MISSING";
|
|
9
|
-
this.name = "SSRDataMissingError";
|
|
10
|
-
Object.setPrototypeOf(this, SSRDataMissingError.prototype);
|
|
11
|
-
}
|
|
12
|
-
};
|
|
13
|
-
//#endregion
|
|
14
|
-
//#region src/common/render-context.ts
|
|
15
|
-
let provider = { getRenderContext() {
|
|
16
|
-
return null;
|
|
17
|
-
} };
|
|
18
|
-
let hydrationRenderData = null;
|
|
19
|
-
let hydrationKeyCounter = 0;
|
|
20
|
-
function configureRenderContextProvider(nextProvider) {
|
|
21
|
-
provider = nextProvider;
|
|
22
|
-
}
|
|
23
|
-
function getActiveRenderContext() {
|
|
24
|
-
return provider.getRenderContext();
|
|
25
|
-
}
|
|
26
|
-
/** Register request-local CSS produced during SSR without importing the SSR renderer in clients. */
|
|
27
|
-
function registerSSRStyle(id, cssText) {
|
|
28
|
-
const context = getActiveRenderContext();
|
|
29
|
-
if (!context?.ssrStyles) return;
|
|
30
|
-
const safeCssText = cssText.replace(/<\/style/gi, "<\\/style");
|
|
31
|
-
const existing = context.ssrStyles.get(id);
|
|
32
|
-
if (existing && existing.cssText !== safeCssText) throw new RangeError(`SSR style registration collision for ${JSON.stringify(id)}.`);
|
|
33
|
-
context.ssrStyles.set(id, {
|
|
34
|
-
id,
|
|
35
|
-
cssText: safeCssText
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
function getCurrentRenderData() {
|
|
39
|
-
return getActiveRenderContext()?.renderData ?? hydrationRenderData;
|
|
40
|
-
}
|
|
41
|
-
function getNextRenderKey() {
|
|
42
|
-
const ctx = getActiveRenderContext();
|
|
43
|
-
if (ctx) return `r:${ctx.keyCounter++}`;
|
|
44
|
-
if (hydrationRenderData) return `r:${hydrationKeyCounter++}`;
|
|
45
|
-
return "r:0";
|
|
46
|
-
}
|
|
47
|
-
function startHydrationRenderPhase(data) {
|
|
48
|
-
hydrationRenderData = data;
|
|
49
|
-
hydrationKeyCounter = 0;
|
|
50
|
-
}
|
|
51
|
-
function stopHydrationRenderPhase() {
|
|
52
|
-
hydrationRenderData = null;
|
|
53
|
-
hydrationKeyCounter = 0;
|
|
54
|
-
}
|
|
55
|
-
function startRenderPhase(data) {
|
|
56
|
-
const ctx = getActiveRenderContext();
|
|
57
|
-
if (ctx) {
|
|
58
|
-
ctx.renderData = data ?? null;
|
|
59
|
-
ctx.keyCounter = 0;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
function stopRenderPhase() {
|
|
63
|
-
const ctx = getActiveRenderContext();
|
|
64
|
-
if (ctx) {
|
|
65
|
-
ctx.renderData = null;
|
|
66
|
-
ctx.keyCounter = 0;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
function throwSSRDataMissing() {
|
|
70
|
-
throw new SSRDataMissingError();
|
|
71
|
-
}
|
|
72
|
-
//#endregion
|
|
73
|
-
export { registerSSRStyle as a, stopHydrationRenderPhase as c, SSRDataMissingError as d, getNextRenderKey as i, stopRenderPhase as l, getActiveRenderContext as n, startHydrationRenderPhase as o, getCurrentRenderData as r, startRenderPhase as s, configureRenderContextProvider as t, throwSSRDataMissing as u };
|
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import { n as Fragment, t as ELEMENT_TYPE } from "./jsx-C3IECePB.js";
|
|
2
|
-
//#region src/jsx/utils.ts
|
|
3
|
-
function isElement(value) {
|
|
4
|
-
return typeof value === "object" && value !== null && value.$$typeof === ELEMENT_TYPE;
|
|
5
|
-
}
|
|
6
|
-
function cloneElement(element, props) {
|
|
7
|
-
return {
|
|
8
|
-
$$typeof: element.$$typeof,
|
|
9
|
-
type: element.type,
|
|
10
|
-
key: element.key,
|
|
11
|
-
props: {
|
|
12
|
-
...element.props,
|
|
13
|
-
...props
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
//#endregion
|
|
18
|
-
//#region src/foundations/structures/layout.tsx
|
|
19
|
-
function layout(Layout) {
|
|
20
|
-
return (children, props) => {
|
|
21
|
-
return Layout({
|
|
22
|
-
...props,
|
|
23
|
-
children
|
|
24
|
-
});
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
//#endregion
|
|
28
|
-
//#region src/foundations/structures/slot.tsx
|
|
29
|
-
/**
|
|
30
|
-
* Slot
|
|
31
|
-
*
|
|
32
|
-
* Structural primitive for prop forwarding patterns.
|
|
33
|
-
*
|
|
34
|
-
* POLICY DECISIONS (LOCKED):
|
|
35
|
-
*
|
|
36
|
-
* 1. asChild Pattern
|
|
37
|
-
* When asChild=true, merges props into the single child element.
|
|
38
|
-
* Child must be a valid JSXElement; non-element children return null.
|
|
39
|
-
* **Slot props override child props** (injection pattern).
|
|
40
|
-
*
|
|
41
|
-
* 2. Fallback Behavior
|
|
42
|
-
* When asChild=false, returns a Fragment (structural no-op).
|
|
43
|
-
* No DOM element is introduced.
|
|
44
|
-
*
|
|
45
|
-
* 3. Type Safety
|
|
46
|
-
* asChild=true requires exactly one JSXElement child (enforced by type).
|
|
47
|
-
* Runtime validates with isElement() check.
|
|
48
|
-
*/
|
|
49
|
-
function Slot(props) {
|
|
50
|
-
if (props.asChild) {
|
|
51
|
-
const { children, asChild: _asChild, ...rest } = props;
|
|
52
|
-
if (isElement(children)) return cloneElement(children, rest);
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
return {
|
|
56
|
-
$$typeof: ELEMENT_TYPE,
|
|
57
|
-
type: Fragment,
|
|
58
|
-
props: { children: props.children },
|
|
59
|
-
key: null
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
//#endregion
|
|
63
|
-
//#region src/foundations/structures/presence.ts
|
|
64
|
-
/**
|
|
65
|
-
* Presence
|
|
66
|
-
*
|
|
67
|
-
* Structural policy primitive for conditional mount/unmount.
|
|
68
|
-
* - No timers
|
|
69
|
-
* - No animation coupling
|
|
70
|
-
* - No DOM side-effects
|
|
71
|
-
*
|
|
72
|
-
* POLICY DECISIONS (LOCKED):
|
|
73
|
-
*
|
|
74
|
-
* 1. Present as Function
|
|
75
|
-
* Accepts boolean OR function to support lazy evaluation patterns.
|
|
76
|
-
* Function is called once per render. Use boolean form for static values.
|
|
77
|
-
*
|
|
78
|
-
* 2. Children Type
|
|
79
|
-
* Presence forwards normal renderable child content only.
|
|
80
|
-
* Imperative DOM nodes are not part of the public contract.
|
|
81
|
-
*
|
|
82
|
-
* 3. Immediate Mount/Unmount
|
|
83
|
-
* No exit animations or transitions. When `present` becomes false,
|
|
84
|
-
* children are removed immediately. Animation must be layered above
|
|
85
|
-
* this primitive.
|
|
86
|
-
*/
|
|
87
|
-
function Presence({ present, children }) {
|
|
88
|
-
if (!(typeof present === "function" ? present() : Boolean(present))) return null;
|
|
89
|
-
return {
|
|
90
|
-
$$typeof: ELEMENT_TYPE,
|
|
91
|
-
type: Fragment,
|
|
92
|
-
props: { children },
|
|
93
|
-
key: null
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
//#endregion
|
|
97
|
-
//#region src/foundations/structures/collection.ts
|
|
98
|
-
function createCollection() {
|
|
99
|
-
const registry = /* @__PURE__ */ new Map();
|
|
100
|
-
function register(node, metadata) {
|
|
101
|
-
const item = {
|
|
102
|
-
node,
|
|
103
|
-
metadata
|
|
104
|
-
};
|
|
105
|
-
registry.set(node, item);
|
|
106
|
-
return () => {
|
|
107
|
-
registry.delete(node);
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
function items() {
|
|
111
|
-
return Array.from(registry.values());
|
|
112
|
-
}
|
|
113
|
-
function clear() {
|
|
114
|
-
registry.clear();
|
|
115
|
-
}
|
|
116
|
-
function size() {
|
|
117
|
-
return registry.size;
|
|
118
|
-
}
|
|
119
|
-
return {
|
|
120
|
-
register,
|
|
121
|
-
items,
|
|
122
|
-
clear,
|
|
123
|
-
size
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* USAGE EXAMPLE:
|
|
128
|
-
*
|
|
129
|
-
* // Create a collection for menu items
|
|
130
|
-
* const menuItems = createCollection<HTMLElement, { disabled: boolean }>();
|
|
131
|
-
*
|
|
132
|
-
* // Register items
|
|
133
|
-
* const unregister1 = menuItems.register(element1, { disabled: false });
|
|
134
|
-
* const unregister2 = menuItems.register(element2, { disabled: true });
|
|
135
|
-
*
|
|
136
|
-
* // Query items
|
|
137
|
-
* const allItems = menuItems.items();
|
|
138
|
-
* const enabledItems = allItems.filter(item => !item.metadata.disabled);
|
|
139
|
-
*
|
|
140
|
-
* // Cleanup
|
|
141
|
-
* unregister1();
|
|
142
|
-
* unregister2();
|
|
143
|
-
*/
|
|
144
|
-
//#endregion
|
|
145
|
-
//#region src/foundations/structures/layer.ts
|
|
146
|
-
function createLayer() {
|
|
147
|
-
const stack = [];
|
|
148
|
-
let nextId = 1;
|
|
149
|
-
function register(options) {
|
|
150
|
-
const id = nextId++;
|
|
151
|
-
const entry = {
|
|
152
|
-
id,
|
|
153
|
-
options
|
|
154
|
-
};
|
|
155
|
-
stack.push(entry);
|
|
156
|
-
function isTop() {
|
|
157
|
-
return stack[stack.length - 1]?.id === id;
|
|
158
|
-
}
|
|
159
|
-
function unregister() {
|
|
160
|
-
const index = stack.findIndex((e) => e.id === id);
|
|
161
|
-
if (index !== -1) stack.splice(index, 1);
|
|
162
|
-
}
|
|
163
|
-
return {
|
|
164
|
-
id,
|
|
165
|
-
isTop,
|
|
166
|
-
unregister
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
function layers() {
|
|
170
|
-
return stack.map((entry) => ({
|
|
171
|
-
id: entry.id,
|
|
172
|
-
isTop: () => stack[stack.length - 1]?.id === entry.id,
|
|
173
|
-
unregister: () => {
|
|
174
|
-
const index = stack.findIndex((e) => e.id === entry.id);
|
|
175
|
-
if (index !== -1) stack.splice(index, 1);
|
|
176
|
-
}
|
|
177
|
-
}));
|
|
178
|
-
}
|
|
179
|
-
function handleEscape() {
|
|
180
|
-
const top = stack[stack.length - 1];
|
|
181
|
-
if (top) top.options.onEscape?.();
|
|
182
|
-
}
|
|
183
|
-
function handleOutsidePointer(e) {
|
|
184
|
-
const top = stack[stack.length - 1];
|
|
185
|
-
if (!top) return;
|
|
186
|
-
const node = top.options.node;
|
|
187
|
-
if (node && e.target instanceof Node) {
|
|
188
|
-
if (!node.contains(e.target)) top.options.onOutsidePointer?.(e);
|
|
189
|
-
} else top.options.onOutsidePointer?.(e);
|
|
190
|
-
}
|
|
191
|
-
return {
|
|
192
|
-
register,
|
|
193
|
-
layers,
|
|
194
|
-
handleEscape,
|
|
195
|
-
handleOutsidePointer
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* USAGE EXAMPLE:
|
|
200
|
-
*
|
|
201
|
-
* const layerManager = createLayer();
|
|
202
|
-
*
|
|
203
|
-
* function Modal({ onClose }) {
|
|
204
|
-
* const modalRef = ref<HTMLDivElement>();
|
|
205
|
-
*
|
|
206
|
-
* const layer = layerManager.register({
|
|
207
|
-
* node: modalRef.current,
|
|
208
|
-
* onEscape: onClose,
|
|
209
|
-
* onOutsidePointer: onClose,
|
|
210
|
-
* });
|
|
211
|
-
*
|
|
212
|
-
* onUnmount(() => layer.unregister());
|
|
213
|
-
*
|
|
214
|
-
* return (
|
|
215
|
-
* <div ref={modalRef}>
|
|
216
|
-
* <h1>Modal</h1>
|
|
217
|
-
* {layer.isTop() && <p>I am on top!</p>}
|
|
218
|
-
* </div>
|
|
219
|
-
* );
|
|
220
|
-
* }
|
|
221
|
-
*/
|
|
222
|
-
//#endregion
|
|
223
|
-
export { layout as a, Slot as i, createCollection as n, cloneElement as o, Presence as r, isElement as s, createLayer as t };
|