Skip to content

Commit 6c5aa4b

Browse files
authored
refactor(lit): tighten A2uiChildRef type (#1520)
1 parent 8e4b5c0 commit 6c5aa4b

2 files changed

Lines changed: 20 additions & 28 deletions

File tree

renderers/lit/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
## Unreleased
22

3+
- (v0_9) Narrow `A2uiChildRef` to the supported child reference shapes used by
4+
`renderNode`.
5+
36
## 0.10.0
47

58
- **BREAKING CHANGE**: (v0_9) Rename Icon `path` property to `svgPath` and update component to correctly render SVG elements.

renderers/lit/src/v0_9/a2ui-lit-element.ts

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,15 @@
1616

1717
import {LitElement, nothing} from 'lit';
1818
import {property} from 'lit/decorators.js';
19-
import {ComponentContext, ComponentApi} from '@a2ui/web_core/v0_9';
19+
import {ComponentContext, ComponentApi, type ComponentId} from '@a2ui/web_core/v0_9';
2020
import {renderA2uiNode} from './surface/render-a2ui-node.js';
2121
import {A2uiController} from '@a2ui/lit/v0_9';
2222

2323
/**
24-
* Represents a reference to a child component that should be rendered.
25-
* In A2UI, a child can be provided in one of three ways:
26-
*
27-
* 1. A string ID (e.g., "submit_button"). Tells the renderer to look up the component
28-
* from the Surface's registry. The child will inherit the parent's data context path.
29-
* 2. A reference object (e.g., { id: 'foo', basePath: '/bar' }). Tells the renderer where
30-
* to find the component AND binds it to a specific slice of the data model.
31-
* 3. An inline component object (e.g., { type: 'Button', props: { ... } }). Provides the
32-
* full component definition directly instead of looking it up by ID.
33-
*
34-
* (This probably should come from the binder in web_core!)
24+
* A reference to a child component to render. Either a string ID, or an object
25+
* pairing an ID with an explicit data context path.
3526
*/
36-
type A2uiChildRef = string | {id?: string; basePath?: string; type?: string};
27+
type A2uiChildRef = ComponentId | {id: ComponentId; basePath: string};
3728

3829
/**
3930
* A base class for A2UI Lit elements that manages the A2uiController lifecycle.
@@ -63,35 +54,33 @@ export abstract class A2uiLitElement<Api extends ComponentApi> extends LitElemen
6354
* Helper method to render a child A2UI node.
6455
* Abstracts away the need to manually create a ComponentContext.
6556
*
66-
* @param childRef The reference to the child component to render. Can be a string ID,
67-
* a reference object containing `{ id, basePath }`, or a full inline component definition.
57+
* @param childRef The reference to the child component to render. Either a string ID
58+
* or a reference object containing `{id, basePath}`.
6859
* @param customPath An explicit data model path to bind the child to. If provided,
69-
* this completely overrides any path defined in the `childRef` object.
70-
* If omitted, it falls back to the `childRef`'s `basePath`, or the current component's path.
60+
* this overrides any path defined in the `childRef` object. If omitted,
61+
* falls back to the `childRef`'s `basePath`, or the current component's path.
7162
*
7263
* @returns A Lit template result containing the rendered child component, or `nothing` if the reference is empty.
7364
*/
7465
protected renderNode(childRef?: A2uiChildRef, customPath?: string) {
7566
if (!childRef) return nothing;
76-
let model: any = childRef;
7767
const {surface, path: parentPath} = this.context.dataContext;
7868

79-
// Path is resolved in the following order:
80-
// customPath > childRef.basePath > parentPath
69+
// Path resolution order: customPath > childRef.basePath > parentPath
70+
let componentId: ComponentId;
8171
let path = customPath;
82-
83-
// We check !childRef.type because an inline component definition (e.g. { type: 'Button' })
84-
// should be passed directly to the ComponentContext. If it doesn't have a .type,
85-
// we treat it as a child reference object (e.g. { id: 'foo', basePath: '/bar' }).
86-
if (typeof childRef === 'object' && childRef !== null && childRef.id && !childRef.type) {
87-
model = childRef.id;
72+
if (typeof childRef === 'object') {
73+
componentId = childRef.id;
8874
path = path ?? childRef.basePath;
75+
} else {
76+
componentId = childRef;
8977
}
9078

91-
// Fallback to the current component's context.
79+
// Keep this fallback because the previous A2uiChildRef type allowed object
80+
// refs without a basePath.
9281
path = path ?? parentPath;
9382

94-
return renderA2uiNode(new ComponentContext(surface, model, path), surface.catalog);
83+
return renderA2uiNode(new ComponentContext(surface, componentId, path), surface.catalog);
9584
}
9685

9786
/**

0 commit comments

Comments
 (0)