( value: unknown, context: EvaluationContext, schemaCtx: SchemaContext, reactiveSchema: unknown | undefined, callbacks: PropEvalCallbacks, )
| 30 | * ReactiveAssign markers, nested ElementNodes, arrays, and ActionPlans. |
| 31 | */ |
| 32 | export function evaluatePropCore( |
| 33 | value: unknown, |
| 34 | context: EvaluationContext, |
| 35 | schemaCtx: SchemaContext, |
| 36 | reactiveSchema: unknown | undefined, |
| 37 | callbacks: PropEvalCallbacks, |
| 38 | ): unknown { |
| 39 | if (value == null) return value; |
| 40 | if (typeof value !== "object") return value; |
| 41 | |
| 42 | // AST node — evaluate with schema context |
| 43 | if (isASTNode(value)) { |
| 44 | // StateRef on reactive prop → ReactiveAssign marker |
| 45 | if (value.k === "StateRef" && reactiveSchema && isReactiveSchema(reactiveSchema)) { |
| 46 | return { |
| 47 | __reactive: "assign" as const, |
| 48 | target: value.n, |
| 49 | expr: { k: "StateRef" as const, n: "$value" }, |
| 50 | }; |
| 51 | } |
| 52 | const result = evaluate(value, context, schemaCtx); |
| 53 | // ElementNode result (from ternary/Comp) → recurse into its props |
| 54 | if (isElementNode(result)) { |
| 55 | return callbacks.recurseElement(result as ElementNode); |
| 56 | } |
| 57 | // Array result (from Each) → recurse into any ElementNodes |
| 58 | if (Array.isArray(result)) { |
| 59 | return result.map((item) => |
| 60 | isElementNode(item) ? callbacks.recurseElement(item as ElementNode) : item, |
| 61 | ); |
| 62 | } |
| 63 | // Strip ReactiveAssign from non-reactive props |
| 64 | if (isReactiveAssign(result) && !(reactiveSchema && isReactiveSchema(reactiveSchema))) { |
| 65 | return context.getState(result.target) ?? null; |
| 66 | } |
| 67 | return result; |
| 68 | } |
| 69 | |
| 70 | // String on reactive schema → pass through (component's useStateField resolves it) |
| 71 | if (typeof value === "string" && reactiveSchema && isReactiveSchema(reactiveSchema)) { |
| 72 | return value; |
| 73 | } |
| 74 | |
| 75 | // Array — recurse |
| 76 | if (Array.isArray(value)) { |
| 77 | return value.map((v) => callbacks.recurse(v, reactiveSchema)); |
| 78 | } |
| 79 | |
| 80 | // ElementNode — recurse with schema |
| 81 | if (isElementNode(value)) { |
| 82 | return callbacks.recurseElement(value as ElementNode); |
| 83 | } |
| 84 | |
| 85 | // ActionPlan / ActionStep — preserve as-is (deferred click-time evaluation) |
| 86 | const obj = value as Record<string, unknown>; |
| 87 | if ("steps" in obj && Array.isArray(obj.steps)) return value; |
| 88 | if ("type" in obj && "valueAST" in obj) return value; |
| 89 |
no test coverage detected